精华内容
下载资源
问答
  • Java的耦合问题

    千次阅读 2020-07-10 12:45:01
    一、耦合问题 1、软件设计的耦合 耦合性是程序结构中各个模块之间相互关联的度量。它取决于各个模块之间的接口的复杂程度、调用模块的方式以及哪些信息通过接口。 软件工程中对象之间的耦合度就是指对象之间的...

    一、耦合问题

    1、软件设计的耦合

    耦合性是程序结构中各个模块之间相互关联的度量。它取决于各个模块之间的接口的复杂程度、调用模块的方式以及哪些信息通过接口。

    • 软件工程中对象之间的耦合度就是指对象之间的依赖性。
    • 对象之间的耦合越高,维护成本也就越高

    2、常见的耦合

    1. 内容耦合
      内容耦合是指一个模块与另一个模块的内部属性有关,不经调用直接使用另一个模块的程序代码或内部数据。
    2. 公共耦合
      公共耦合指通过一个公共数据环境相互作用的那些模块间的耦合,公共数据环境可以是全程变量或数据结构共享的通信,内存的公共覆盖区及任何存储介质上的文件。
      物理设备(也有将公共外部设备分类为外部耦合),由于两个模块都需引用同一个公共数据域,因此有较高的耦合度。
    3. 控制耦合/外部耦合
      一个模块通过接口向另一个模块传递一个控制信号,接收信号的模块根据信号值而进行适当的动作,这种耦合被称为控制耦合。
    4. 标记耦合
      若一个模块A通过接口向两个模块B和C传递一个公共参数,那么模块B和模块C之间存在一个标记耦合。
    5. 数据耦合
      模块之间通过参数来传递数据,那么被称为数据耦合。
      数据耦合是最低的一种耦合形式,系统中一般都存在这种类型的耦合,为了完成一些有意义的操作,往往需要将某些模块的输出数据作为另一些模块的输入数据
    6. 非直接耦合
      两个模块之间没有直接关系,他们之间的联系完全是通过主模块的控制和调用来实现的。

    3、耦合的解决方案

    • 耦合在一起的模块,如果一方发生了变化肯定会影响另一方,这样的话独立性降低危险度提高,维护成本自然就高了。
    • 如果必须用耦合的话,尽量使用数据耦合,少用控制耦合,限制公共耦合范围,避免内容耦合。
    • 高内聚低耦合是软件设计的最终解决思路,但高内聚意味着编码成本的增加,所以完美的高内聚是不存在的,所以适度设计即可。(内聚是指什么功能都由自己内部实现,不需要依靠外部任何资源)

    二、耦合的小例子

    1、最初版本

    • 实体类
    package com.gaj.entity;
    
    /**
     * Java实体类
     * @author Jan
     *
     */
    public class UserInfo {
    	private Integer id;
    	private String name;
    	
    	public Integer getId() {
    		return id;
    	}
    	public void setId(Integer id) {
    		this.id = id;
    	}
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	
    	@Override
    	public String toString() {
    		return "UserInfo [id=" + id + ", name=" + name + "]";
    	}
    }
    
    
    • DAO层
    package com.gaj.dao;
    
    import com.gaj.entity.UserInfo;
    
    /**
     * 模拟获得对象及属性
     * @author Jan
     *
     */
    public class UserInfoDAO {
    	public UserInfo findUserById(Integer id){
    		// 创建方法返回值
    		UserInfo user = new UserInfo();
    		// 设置属性
    		user.setId(1);
    		user.setName("张三");
    		//返回
    		return user;
    	}
    }
    
    
    • Service层
    package com.gaj.service;
    
    import com.gaj.dao.UserInfoDAO;
    import com.gaj.entity.UserInfo;
    
    public class UserInfoService {
    	
    	private UserInfoDAO userDao = new UserInfoDAO();
    	
    	public UserInfo findUserById(Integer id){
    		return userDao.findUserById(id);
    	}
    	
    }
    
    
    • Test类
    package com.gaj.test;
    
    import org.junit.Test;
    
    import com.gaj.entity.UserInfo;
    import com.gaj.service.UserInfoService;
    
    public class MyTest {
    
    	@Test
    	public void findUserById(){
    		UserInfoService service = new UserInfoService();
    		UserInfo user = service.findUserById(1);
    		System.out.println(user);
    	}
    	
    }
    

    测试类是可以拿到结果的,但是类与类之间耦和度比较高。测试类依赖Service层的对象,Service层依赖DAO层的对象,DAO层依赖实体层的对象。
    在这里插入图片描述
    更改被引用类的类名,会直接影响到引用该类的类
    在这里插入图片描述

    2、引入接口降低耦合

    • DAO层接口
    package com.gaj.dao;
    
    import com.gaj.entity.UserInfo;
    
    
    public interface UserInfoDAO {
    	
    	public UserInfo findUserById(Integer id);
    	
    }
    
    
    • DAO层实现类
    package com.gaj.dao.Impl;
    
    import com.gaj.dao.UserInfoDAO;
    import com.gaj.entity.UserInfo;
    /**
     * 模拟获得对象及属性
     * @author Jan
     *
     */
    public class UserInfoDAOImplement implements UserInfoDAO{
    
    	@Override
    	public UserInfo findUserById(Integer id){
    		// 创建方法返回值
    		UserInfo user = new UserInfo();
    		// 设置属性
    		user.setId(1);
    		user.setName("张三");
    		//返回
    		return user;
    	}
    	
    }
    
    
    • Service层接口
    package com.gaj.service;
    
    import com.gaj.entity.UserInfo;
    
    public interface UserInfoService {
    
    	public UserInfo findUserById(Integer id);
    	
    }
    
    
    • Service层实现类
    package com.gaj.service.impl;
    
    import com.gaj.dao.UserInfoDAO;
    import com.gaj.dao.Impl.UserInfoDAOImplement;
    import com.gaj.entity.UserInfo;
    import com.gaj.service.UserInfoService;
    
    public class UserInfoServiceImplement implements UserInfoService {
    	
    	private UserInfoDAO userDao = new UserInfoDAOImplement();
    	
    	public UserInfo findUserById(Integer id){
    		return userDao.findUserById(id);
    	}
    	
    }
    
    
    • 测试类
    package com.gaj.test;
    
    import org.junit.Test;
    
    import com.gaj.entity.UserInfo;
    import com.gaj.service.UserInfoService;
    import com.gaj.service.impl.UserInfoServiceImplement;
    
    public class MyTest {
    
    	@Test
    	public void findUserById(){
    		UserInfoService service = new UserInfoServiceImplement();
    		UserInfo user = service.findUserById(1);
    		System.out.println(user);
    	}
    }
    
    

    耦合当然是存在的,但如果不new对象,就能减少耦合了。(将控制耦合转化为数据耦合)

    3、利用反射技术进一步降低耦合

    利用反射技术,将控制耦合转化为数据耦合。

    	@Test
    	public void findUserById2() throws Exception{
    		UserInfoService service = (UserInfoService) Class.forName("com.gaj.service.impl.UserInfoServiceImplement").newInstance();
    		UserInfo user = service.findUserById(1);
    		System.out.println(user);
    	}
    

    把本来的类与类之间的耦合降低为类与字符串之间的耦合,但要创建对象的类的权限定名写在了java文件里,也意味着如果修改这个创建对象的类名的话必须把当前这个java文件重新编译。

    4、将XML作为配置文件保存类全限定名

    因为XML是程序的元语言文件,XML是不需要任何编译器就能直接被计算机识别,HTML就是XML的一种高级应用,写HTML的时候只
    需要一个记事本,写完了无需编译直接扔到浏览器就能运行,所以可以利用XML的特性把要创建对象的类以某种自定义格式扔到XML中,然后用Java技术读取XML,读取到之后再反射生成对象。
    语法:

    头部标记 : 
    <?xml version="1.0" encoding="UTF-8"?>
    单标签 : 
    <标签名称 属性1="值1" 属性2="值2" .... 属性N="值N" />
    双标签 : 
    <标签名称 属性1="值1" 属性2="值2" .... 属性N="值N">标签之间的内容</标签名称>
    

    将需要创建对象的部分都放到XML文件中
    applicationContext.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans>
    	<bean id="userDao" class="com.gaj.dao.Impl.UserInfoDAOImplement" />
    	<bean id="service" class="com.gaj.service.impl.UserInfoServiceImplement" />
    </beans>
    

    5、dom4j工具解析XML文件

    dom4j是一个Java的XML API,是jdom的升级品,用来读写XML文件的。dom4j是一个十分优秀的JavaXML API,具有性能优异、功能强大和极其易使用的特点,它的性能超过sun公司官方的dom技术,同时它也是一个开放源代码的软件,可以在SourceForge上找到它。在IBM developerWorks上面还可以找到一篇文章,对主流的Java XML API进行的性能、功能和易用性的评测,因此可以知道dom4j无论在哪个方面都是非常出色的。如今可以看到越来越多的Java软件都在使用dom4j来读写XML,特别值得一提的是连Sun的JAXM也在用dom4j。这已经是必须使用的jar包,Hibernate也用它来读写配置文件。

    • 解析XML的dom4j的jar包:
      在这里插入图片描述
    • 测试dom4j
    	@Test
    	public void dom4jTest() throws DocumentException{
    		// 获取xml的位置
    		InputStream in = this.getClass().getClassLoader().getResourceAsStream("applicationContext.xml");
    		// 开始解析
    		// 1.将xml加载到内存中	相当于在内存中将字节流转化为XML文件
    		Document document = new SAXReader().read(in);
    		// 2.获取xml的beans根节点
    		Element beans = document.getRootElement();
    		// 3.获取根节点下的所有bean子节点 保存到List集合
    		List<Element> elements = beans.elements("bean");
    		// 4.解析id属性和class属性
    		for(Element e : elements){
    			// 获取id属性
    			String id = e.attributeValue("id");
    			// 获取class属性
    			String clazz = e.attributeValue("class");
    			// 输出
    			System.out.println(id + "\t\t" + clazz);
    		}
    	}
    }
    

    6、简单工厂模式

    拿类名创建对象,然后拿id值作为key,将这些创建的对象再保存到一个Map集合里去,程序用到的时候用map的key获取某个对象这样我们就不用new这个对象了,这个工具类可以通过读取XML的形式创建其他类的对象,也就是说创建所有类的对象都可以通过这一个类来创建,那么这个专门用来创建对象的类就是对象工厂类,而这种设计模式被叫做简单工厂设计模式。
    简单工厂模式获取目标对象有什么好处呢?使用工厂模式隐藏创建对象细节,这样可以统一对象管理,如果要修改某些实例对象只需要修改工厂方法即可,这样引用工厂的那些个类都不用修改。

    • 编写工厂类
      BeanFactory.java
    package com.gaj.utils;
    
    import java.io.InputStream;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import org.dom4j.Document;
    import org.dom4j.DocumentException;
    import org.dom4j.Element;
    import org.dom4j.io.SAXReader;
    
    /**
     * 工厂类 读取xml文件通过bean标签的class属性值创建对象
     * 
     * @author Jan
     *
     */
    public class BeanFactory {
    
    	// 定义对象保存容器
    	private static Map<String, Object> objs = new HashMap<String, Object>();
    
    	static {
    		// 获取xml的位置
    		InputStream is = BeanFactory.class.getClassLoader().getResourceAsStream("applicationContext.xml");
    		// 1.将xml加载到内存中:字节流 -> xml文件
    		try {
    			Document document = new SAXReader().read(is);
    			// 2.获取xml的根节点 beans
    			Element beans = document.getRootElement();
    			// 3.获取根节点下的所有子节点 bean
    			List<Element> bean = beans.elements("bean");
    			// 4. 循环解析id属性和class属性
    			for (Element e : bean) {
    				String id = e.attributeValue("id");
    				String clazz = e.attributeValue("class");
    				// 通过类名创建对象
    				Object obj = Class.forName(clazz).newInstance();
    				// 保存到Map集合
    				objs.put(id, obj);
    			}
    		} catch (DocumentException e1) {
    			e1.printStackTrace();
    		} catch (InstantiationException e1) {
    			e1.printStackTrace();
    		} catch (IllegalAccessException e1) {
    			e1.printStackTrace();
    		} catch (ClassNotFoundException e1) {
    			e1.printStackTrace();
    		}
    
    	}
    
    	/**
    	 * 根据对象id获取对象
    	 * 
    	 * @param id
    	 * @return 返回该id的class类
    	 */
    	public static <T> T getBean(String id) {
    		Object obj = objs.get(id);
    		if (null != obj) {
    			return (T) obj;
    		} else {
    			return null;
    		}
    	}
    }
    
    
    • 修改Service实现类
    package com.gaj.service.impl;
    
    import com.gaj.dao.UserInfoDAO;
    import com.gaj.dao.Impl.UserInfoDAOImplement;
    import com.gaj.entity.UserInfo;
    import com.gaj.service.UserInfoService;
    import com.gaj.utils.BeanFactory;
    
    public class UserInfoServiceImplement implements UserInfoService {
    	
    	private UserInfoDAO userDao = BeanFactory.getBean("userDao");
    	
    	public UserInfo findUserById(Integer id){
    		return userDao.findUserById(id);
    	}
    	
    }
    
    
    • 修改测试类
    	@Test
    	public void findUserById(){
    		UserInfoService service = BeanFactory.getBean("service");
    		UserInfo user = service.findUserById(1);
    		System.out.println(user);
    	}
    

    7、自定义IOC

    IOC:(Inversion Of Control)控制反转,对象的创建权限由本类交给了工厂创建,对这种对象创建权限的移交叫控制反转。

    • IOC是什么?
      控制反转,把类创建自己对象的权利交给框架,让框架统一管理对象;
    • 为什么要用IOC创建对象呢?
      解耦和,IOC能把两个类的硬耦合(编程阶段耦合在了一起)编程两个类的软耦合(程序运行期间耦合在了一起),这样互不干扰,特别开心;
    • 在哪些地方使用IOC?
      框架应用中使用比较频繁
    • 怎么用IOC?
      1)定义对象容器
      2)工厂模式获取对象
    • IOC的作用?
      消除计算机程序对象的耦合
    展开全文
  • Java编程思想之低耦合

    2016-11-25 20:34:42
    1. 低耦合(Low Coupling) “低耦合”这个词相信大家已经耳熟能详,我们在看spring的书籍、MVC的数据、设计模 式的书籍,无处不提到“低耦合、高内聚”,它已经成为软件设计质量的标准之一。那么什么是低耦合?...

    1.    低耦合(Low Coupling)

    “低耦合”这个词相信大家已经耳熟能详,我们在看spring的书籍、MVC的数据、设计模 式的书籍,无处不提到“低耦合、高内聚”,它已经成为软件设计质量的标准之一。那么什么是低耦合?耦合就是对某元素与其它元素之间的连接、感知和依赖的量 度。这里所说的元素,即可以是功能、对象(类),也可以指系统、子系统、模块。假如一个元素A去连接元素B,或者通过自己的方法可以感知B,或者当B不存 在的时候就不能正常工作,那么就说元素A与元素B耦合。耦合带来的问题是,当元素B发生变更或不存在时,都将影响元素A的正常工作,影响系统的可维护性和 易变更性。同时元素A只能工作于元素B存在的环境中,这也降低了元素A的可复用性。正因为耦合的种种弊端,我们在软件设计的时候努力追求“低耦合”。低耦 合就是要求在我们的软件系统中,某元素不要过度依赖于其它元素。请注意这里的“过度”二字。系统中低耦合不能过度,比如说我们设计一个类可以不与JDK耦 合,这可能吗?除非你不是设计的Java程序。再比如我设计了一个类,它不与我的系统中的任何类发生耦合。如果有这样一个类,那么它必然是低内聚(关于内 聚的问题我随后讨论)。耦合与内聚常常是一个矛盾的两个方面。最佳的方案就是寻找一个合适的中间点。

    哪些是耦合呢?

    1.元素B是元素A的属性,或者元素A引用了元素B的实例(这包括元素A调用的某个方法,其参数中包含元素B)。

    2.元素A调用了元素B的方法。

    3.元素A直接或间接成为元素B的子类。

    4.元素A是接口B的实现。

    幸运的是,目前已经有大量的框架帮助我们降低我们系统的耦合度。比如,使用struts我们 可以应用MVC模型,使页面展现与业务逻辑分离,做到了页面展现与业务逻辑的低耦合。当我们的页面展现需要变更时,我们只需要修改我们的页面,而不影响我 们的业务逻辑;同样,我们的业务逻辑需要变更的时候,我们只需要修改我们的java程序,与我们的页面无关。使用spring我们运用IoC(反向控 制),降低了业务逻辑中各个类的相互依赖。假如类A因为需要功能F而调用类B,在通常的情况下类A需要引用类B,因而类A就依赖于类B了,也就是说当类B 不存在的时候类A就无法使用了。使用了IoC,类A调用的仅仅是实现了功能F的接口的某个类,这个类可能是类B,也可能是另一个类C,由spring的配 置文件来决定。这样,类A就不再依赖于类B了,耦合度降低,重用性提高了。使用hibernate则是使我们的业务逻辑与数据持久化分离,也就是与将数据 存储到数据库的操作分离。我们在业务逻辑中只需要将数据放到值对象中,然后交给hibernate,或者从hibernate那里得到值对象。至于用 Oracle、MySQL还是SQL Server,如何执行的操作,与我无关。

    但是,作为优秀的开发人员,仅仅依靠框架提供的降低软件耦合的方法是远远不够的。根据我的经验,以下一些问题我们应当引起注意:

    1)   根据可能的变化设计软件

    我们采用职责驱动设计,设计中尽力做到“低耦合、高内聚”的一个非常重要的前提是,我们的软 件是在不断变化的。如果没有变化我们当然就不用这么费劲了;但是如果有变化,我们希望通过以上的设计,使我们在适应或者更改这样的变化的时候,付出更小的 代价。这里提供了一个非常重要的信息是,我们努力降低耦合的是那些可能发生变更的地方,因为降低耦合是有代价的,是以增加资源耗费和代码复杂度为代价的。 如果系统中某些元素不太可能变更,或者降低耦合所付出的代价太大,我们当然就应当选择耦合。有一次我试图将我的表现层不依赖于struts,但发现这样的 尝试代价太大而失去意义了。对于软件可能变更的部分,我们应当努力去降低耦合,这就给我们提出一个要求是,在软件设计的时候可以预判日后的变化。根据以往 的经验我认为,一个软件的业务逻辑和采用的技术框架往往是容易变化的2个方面。客户需求变更是我们软件设计必须考虑的问题。在RUP的开发过程中,为什么 需要将分析设计的过程分为分析模型和设计模型,愚以为,从分析模型到设计模型的过程实际上是系统从满足直接的客户需求到优化系统结构、适应可预见的客户需 求变更的一个过程。这种客户需求的变更不仅仅指对一个客户需求的变更,更是指我们的软件从适应一个客户需求到适应更多客户需求的过程。另一个方面,现在技 术变更之快,EJB、hibernate、spring、ajax,一个一个的技术像走马灯一样从我们脑海中滑过,我们真不知道明天我在用什么。在这样的 情况下,适应变化就是我们最佳的选择。

    2)   合理的职责划分

    合理的职责划分,让系统中的对象各司其职,不仅是提高内聚的要求,同时也可以有效地降低耦 合。比如评审计划BUS、评审表BUS、评审报告BUS都需要通过评审计划DAO去查询一些评审计划的数据,如果它们都去直接调用评审计划DAO(如图 A),则评审计划BUS、评审表BUS、评审报告BUS三个对象都与评审计划DAO耦合,评审计划DAO一旦变更将与这三个对象都有关。在这个实例中,实 际上评审计划BUS是信息专家(关于信息专家模式我将在后面讨论),评审表BUS和评审报告BUS如果需要获得评审计划的数据,应当向评审计划BUS提出 需求,由评审计划BUS提供数据(如图B)。经过这样的调整,系统的耦合度就降低了。

    3)   使用接口而不是继承

    通过对耦合的分析,我们不难发现,继承就是一种耦合。如果子类A继承了父类B,不论是直接或 间接的继承,子类A都必将依赖父类B。子类A必须使用在存在父类B的环境中,父类B不存在子类A就不能使用,这样将影响子类A的可移植性。一旦父类B发生 任何变更,更改或去掉一个函数名,或者改变一个函数的参数,都将导致子类A不得不变更,甚至重写。假如父类B的子类数十上百个,甚至贯穿这个项目各个模 块,这样的变更是灾难性的。这种情况最典型的例子是我们现在使用hibernate和spring设计DAO对象的方式,具体的描述参见我写的《如何在 struts + spring + hibernate的框架下构建低耦合高内聚的软件结构》一文。

    总之,“低耦合”给软件项目带来的优点是:易于变更、易于重用。

    展开全文
  • 面向对象编程中的聚合与耦合

    千次阅读 2018-06-10 11:30:01
    在面向对象的设计中,我们经常会听到或用到聚合、耦合的概念。面向对象的目标就是设计出高聚合、低耦合的程序。然而,究竟什么是聚合、什么是耦合,恐怕每个人都有自己的答案,换句话说,大多数人对聚合和耦合的概念...

    在面向对象的设计中,我们经常会听到或用到聚合、耦合的概念。面向对象的目标就是设计出高聚合、低耦合的程序。然而,究竟什么是聚合、什么是耦合,恐怕每个人都有自己的答案,换句话说,大多数人对聚合和耦合的概念是模糊的。小弟我今天就在此抛砖引玉,希望能给新入行的朋友和在校的学生一点帮助。

    因为聚合与耦合这两个概念一直都是以"高聚合、低耦合"的形式出现的,刚刚开始接触面向对象设计时,我一直认为聚合和耦合是一对相反的概念,也就是说:只要做到了高聚合,那么自然而然就做到了低耦合。虽然这样的理解并不是错误的,但我并没有思考过原因。

    先来看看聚合的定义:聚合(Cohesion)是一个模块内部各成分之间相关联程度的度量。

    这里有多个含义值得考虑。首先,聚合是对一个模块内部的度量,这也是许多情况下我们把聚合称之为内聚的原因。第二,这里出现的模块是广义的模块,它可能是子系统,可能是功能模块,也可能是功能模块中的某一个类。从不同的层次看,聚合的程度也会有所不同。至于为什么不同,后面会有解释。第三,模块的成分包括模块的行为和状态。要做到高聚合,那么模块内部的行为必须要与模块的内部状态紧密关联。通俗来讲,一个模块仅完成一个独立的功能,模块内部不存在与该功能无关的操作或状态。

    举一个生活中的例子。

    有两座城市Sidtown和Fredborough,连接两座城市的公路一天到晚总是拥堵不堪。经过"有关部门"调查之后发现,这两座城市中有两家公司Better Mousetrap和 Zokko Soda,Better Mousetrap的工厂建造在Sidtown,而该工厂的员工都居住在Fredborough,所以每天早上大批员工从Fredborough出发前往Sidtown,并在傍晚返回;类似的,Zokko Soda公司的运输车在每天的工作时间都需要在制瓶工厂和灌装工厂穿梭来往。


    很明显,如果Better Mousetrap的工厂和员工居住地都在同一城市,而Zokko Soda的两座工厂都建造在另一座城市,那么城市之间的交通状况将会明显改善。


    对比两图,上面两座城市间之所以出现交通的问题,是因为每座城市的"聚合性"都比较低:不相关的两个公司出现在了同一座城市,使得城市内部交通的利用率比较低,而城市之间的交通出现了超负荷。

    再来看看耦合的定义:耦合(Couping)是模块之间相关联程度的度量。相对于聚合的内向性,耦合关注的是某一模块和其他模块之间的关联性。其实从前面的例子里,我们已经不可避免的提到了耦合的问题:由于两座城市之间的相互联系过于紧密,导致了城市之间的交通拥堵。另外一个潜在的问题就是,如果其中一座城市内部的交通出现了问题,另一座城市也会受到影响。我们所追求的低耦合,就是将两个模块之间的关联尽可能的降低,一个模块发生变化对于其他模块的影响尽可能的小。

    再讲一个生活中的例子,相信大部分的80后小的时候都玩过一种掌上游戏机,这种游戏机内含一个俄罗斯方块的游戏。这种游戏机虽然风靡一时,但是不多久就渐渐淡出了市场,因为这种游戏机只有俄罗斯方块可以玩儿,当我们玩儿腻了的时候,这个游戏机也就如同废物一个了。

    同期,任天堂推出一款后来风靡了将近20年的红白机,这种游戏机市场寿命如此之长并非游戏机本身质量有多好,而是因为基于红白机开发的游戏层出不穷,经典无数。魂斗罗、超级玛丽在当时哪怕是现在也是无人不知。红白机的游戏本身并不存储在游戏机当中,每当有新游戏推出的时候,只需要购买新的卡带即可。正是这种游戏机和卡带相对独立的设计,使得游戏的设计厂商无需关心游戏机的实现细节,只要遵循游戏机提供的接口(插槽)。很多游戏的设计厂商也从红白机庞大的市场中分得一杯羹。大多数的玩家可能不知道,魂斗罗并非任天堂推出的产品,而是目前以《实况足球》系列闻名世界的KONAMI公司于1988年从街机移植到红白机上的。

    回到耦合的话题上来,因为早先的掌上游戏机将游戏本身内置在机器当中,游戏和机器这两个模块之间的关系过于紧密,所以游戏玩儿腻了,游戏机就没用了,游戏机出问题了,游戏也再也不能玩儿了。而红白机的游戏和游戏机之间的关系是相对独立的,只要它们都遵循制定好的协议,就可以独立的发展和变化。游戏卡带摔坏了,其他的游戏一样可以在机器上运行;自己的游戏机坏了,把卡带拿到朋友家的游戏机上也能玩儿。红白机发展到后期,连游戏机的手柄也是可插拔的,如果手柄坏了,也只需要更换手柄即可。

    讲到这里,大家对聚合和耦合应该也有了初步的认识。那么,我们如何看待聚合和耦合在实际当中的应用呢?我们的程序怎样才算是做到了高聚合和低耦合呢?

    前面曾经提到,从不同的层次看,聚合和耦合的程度也会有所不同。Sidtown和Fredborough的例子当中,从城市的层次来看,第二种设计完全达到了高内聚和低耦合的目标,然而,如果从城市的不同区域来看,这样的设计内聚性还不够。如果我们一直追究下去,恐怕Better Mousetrap所有的员工都要住在生产线上了。一味的追求高内聚,必然会造成模块的功能过于单一,而模块的数量出现急剧膨胀。所以,我们在设计和实现程序时必须要斟酌模块间的聚合和耦合程度,有兴趣的朋友也可以去研究聚合性指标与耦合性指标。


    转自点击打开链接

    展开全文
  • 怎么说呢,一个人要开发大型软件是很没效率的,所以就要有很多人共同开发,懂吧 那么很多人共同开发,你不能所有人都开发一个模块,一个功能,一个...一个模块这个概念比较抽象,可以说是一个编程语言文件,也可...

    怎么说呢,一个人要开发大型软件是很没效率的,所以就要有很多人共同开发,懂吧

    那么很多人共同开发,你不能所有人都开发一个模块,一个功能,一个文件对吧,是不是要有个分工呢?比如说做一个程序,有人开发数据库方面的东西,有人开发网络方面的东西,有人开发界面方面的东西,这就是分工。

    那么分工,每一个分工,也就相当于一个模块,而一个模块就是一个功能。一个模块这个概念比较抽象,可以说是一个编程语言文件,也可以说是一个人所作的工作,也可能说是一个具体功能。

    无论如何,模块之间都要有一定的联系,比如说我的网络链接模块需要用你数据库模块的数据,这个懂吧。那么这些模块之间的连接性,就是耦合性⋯⋯

    有个例子很容易明白:一个程序有50个函数,这个程序执行得非常好;然而一旦你修改其中一个函数,其他49个函数都需要做修改,这就是高耦合的后果。
    一旦你理解了它,你编写概要设计的时候设计类或者模块自然会考虑到“高内聚,低耦合”。

    高内聚是指一个软件模块是由相关性很强的代码组成,只负责一项任务,也就是常说的单一责任原则。低耦合是指让每个模块尽可能的独立完成某个特定的子功能。

    以下的都是一些扯淡话,不食人间烟火的那种:(可以不看,我只是做个记录)

    软件工程中耦合
       简单地说,软件工程中对象之间的耦合度就是对象之间的依赖性。指导使用和维护对象的主要问题是对象之间的多重依赖性。对象之间的耦合越高,维护成本越高。因此对象的设计应使类和构件之间的耦合最小。
      有软硬件之间的耦合,还有软件各模块之间的耦合。
      耦合性是程序结构中各个模块之间相互关联的度量。它取决于各个模块之间的接口的复杂程度、调用模块的方式以及哪些信息通过接口。
      耦合可以分为以下几种,它们之间的耦合度由高到低排列如下:
      (1) 内容耦合。当一个模块直接修改或操作另一个模块的数据时,或一个模块不通过不正常入口而转入另一个模块时,这样的耦合被称为内容耦合。内容耦合是最高程度的耦合,应该避免使用之。
      (2) 公共耦合。两个或两个以上的模块共同引用一个全局数据项,这种耦合被称为公共耦合。在具有大量公共耦合的结构中,确定究竟是哪个模块给全局变量赋了一个特定的值是十分困难的。
      (3) 外部耦合 。一组模块都访问同一全局简单变量而不是同一全局数据结构,而且不是通过参数表传递该全局变量的信息,则称之为外部耦合。
      (4) 控制耦合 。一个模块通过接口向另一个模块传递一个控制信号,接受信号的模块根据信号值而进行适当的动作,这种耦合被称为控制耦合。
      (5) 标记耦合 。若一个模块A通过接口向两个模块B和C传递一个公共参数,那么称模块B和C之间存在一个标记耦合。
      (6) 数据耦合。模块之间通过参数来传递数据,那么被称为数据耦合。数据耦合和最低的一种耦合形式,系统中一般都存在这种类型的耦合,因为为了完成一些有意义的功能,往往需要将某些模块的输出数据作为另一些模块的输入数据。
      (7) 非直接耦合 。两个模块之间没有直接关系,它们之间的联系完全是通过主模块的控制和调用来实现的
      总结:耦合是影响软件复杂程度和设计质量的一个重要因素,在设计上我们应采用以下原则:如果模块间必须存在耦合,就尽量使用数据耦合,少用控制耦合,限制公共耦合的范围,尽量避免使用内容耦合。

    展开全文
  • Java编程思想之高内聚低耦合

    千次阅读 2020-05-18 22:56:16
    编程的时候,经常要使得系统高内聚、低耦合,那么,我们口中的这些概念到底是什么?什么是高内聚低耦合呢? 2 低耦合 耦合性定义 起因 模块独立性指每个模块只完成系统要求的独立子功能,并且与其他模块的联系最少...
  • 面向对象IOS编程中的聚合与耦合

    千次阅读 2014-02-11 21:35:17
    在面向对象的设计中,我们经常会听到或用到聚合、耦合的概念。面向对象的目标就是设计出高聚合、低耦合的程序。然而,究竟什么是聚合、什么是耦合,恐怕每个人都有自己的答案,换句话说,大多数人对聚合和耦合的概念...
  • 如果你涉及软件开发,可能会经常听到“高内聚,低耦合”这种概念型词语。我在第一次接触这种词语时,也抱有很大的疑问,但我发现百度上大部分都是高大上的词汇解释。 仔细通读这篇文章,你就能理解耦合性和内聚性的...
  • 高内聚低耦合,是软件工程中的概念,是判断设计好坏的标准,主要是面向对象的设计,主要是看类的内聚性是否高,耦合度是否低。 2、概念 耦合性:也称块间联系。指软件系统结构中各模块间相互联系紧密程度的一种...
  • 设计模式追求的目的就是“高内聚、低耦合”,在实际编程中运用设计模式能够使我们工程代码更规范、重用性更高,同时也能保证代码的可靠性、提高开发效率。   一、概述  面向对象编程有七大原则,即经常...
  • 这个把四旋翼是高耦合,现在你再回看编程里面强调的 高内聚 低耦合 也应该明白什么意思, 低耦合应该就是指不同模块之间相互影响不大,就我更改或者更新一个模块不会影响到其他模块,这样也方便团队开发。...
  • 如何理解"高内聚低耦合"编程原则呢,有哪些实际的例子呢?恳请指教!
  • 高内聚,低耦合 高内聚:一个C文件里面的函数只有相互之间的调用,而没有调用其他文件里面的函数,这样可以视为高内聚。尽量减少不同文件里面函数的交叉引用。   低耦合:一个完整的系统,模块与模块之间,尽可能的...
  • 耦合性和解耦合性的理解

    千次阅读 2018-09-25 15:26:08
    编程里面 是指一个程序模块与其他模块的联系。如果存在联系,就叫做耦合,我们知道总会有必要的耦合,因此解耦是指把这些联系减少到必要的联系即可。所谓“高聚合,低耦合”就是指这个道理。   那这样有什么...
  • 华为C语言编程规范(精华总结)

    万次阅读 多人点赞 2020-03-24 09:48:55
    很多现有代码中头文件过大,职责过多,再加上循环依赖的问题,可能导致为了在.c中使用一个宏,而包含十几个头文件。 错误示例:某平台定义WORD类型的头文件: #include #include #include #include #include #...
  • 它探讨了函数式编程的概念,允许在Java语言中进行函数式编程的框架,在JVM上运行的函数式编程语言以及语言设计的一些未来方向。 该系列面向那些了解Java及其抽象如何工作,但很少或没有使用功能语言经验的开发人员...
  • 耦合程度

    2016-12-19 15:34:59
    程度耦合
  • 耦合度&如何降低耦合

    千次阅读 2018-07-03 13:44:35
    一、什么是耦合度  耦合度就是某模块(类)与其它模块(类)之间的关联、感知和依赖的程度,是衡量代码独立性的一个指标,也是软件工程设计及编码质量评价的一个标准。耦合的强度依赖于以下几个因素:(1)一个模块...
  • 1.封装、继承、多态 封装,隐藏内部实现 继承,复用现有代码 多态,改写对象行为 继承是以封装为基础的,多态是以...3.面向对象的根本性问题 我们为什么要使用面向对象? 我们应该怎样使用三大机制来实现好的面向对象
  • 从踏入编程世界开始,无论是在学习理论知识的课本上,还是在进行项目过程中,我们经常听到大家一次次的念叨“代码模块尽量做到低耦合、高内聚“”,那么什么是耦合?怎样做到低耦合?怎么进行解耦合实现低耦合,下面...
  • 代码耦合

    千次阅读 2018-10-06 13:02:27
    代码耦合:一个软件结构内不同模块之间互连程度的度量(耦合性也叫块间联系。指软件系统结构中各模块间相互联系紧密程度的一种度量。模块之间联系越紧密,其耦合性就越强,模块的独立性则越差,模块间耦合的高低取决...
  • GNSSINS耦合模式

    2021-03-02 23:08:11
    GNSS/INS耦合模式(一) 围绕着对GNSS信号数据和INS信号数据进行融合处理,(常用的融合方法是卡尔曼滤波),产生了各种GNSS/INS集成架构...优点:不涉及GPS跟踪环路内部结构,硬件实现或软件编程都比较简单 缺点:在进
  • 耦合

    2016-04-25 17:07:27
    一、什么是耦合度 耦合度就是某模块(类)与其它模块(类)之间的关联、感知和依赖的程度,是衡量代码独立性的一个指标,也是软件工程设计及编码质量评价的一个标准。耦合的强度依赖于以下几个因素:(1)一个模块...
  • 耦合概念

    千次阅读 2020-08-29 21:52:04
    一、什么是耦合度 软件设计中通常用耦合度和内聚度作为衡量模块独立程度的标准。划分摸块的一个准则就是高内聚低耦合耦合的强弱取决与模块间接口的复杂性、调用模块的方式以及通过界面传送数据的多少。 模块间的...
  • 耦合性(Coupling),也叫耦合度 定义:是对模块间关联程度的度量。(是一个抽象的度量单位) 耦合的强弱取决于模块间接口的复杂性、调用模块的方式以及通过界面传送数据的多少。 模块间的耦合度是指模块之间的依赖...
  • 耦合方式:在一个Converged应用中,SIP Servlet和HTTP Servlet(或其他J2EE编程模式)分别独立实现,各自执行独立的功能,代码中没有互相调用,两种类型的Servlet上下文及相关配置分别在sip.xml和web.xml文件中...
  • 面向过程编程,面向对象编程和面向切面编程理解

    千次阅读 多人点赞 2017-03-17 19:28:55
    面向过程(Procedure Oriented)是一种以过程为中心的编程思想。这些都是以什么正在发生为主要目标进行编程,不同于面向对象的是谁在受影响。与面向对象明显的不同就是封装、继承、类。面向对象编程(Object Oriented ...
  • 耦合 高内聚

    千次阅读 2012-07-15 02:06:36
    什么是耦合?  内聚,是从功能角度来衡量模块内的联系,一个好的内聚模块应当恰好做一件事。它描述的是模块内的功能联系; 耦合,是从模块角度来衡量软件结构中各模块之间相互连接的一种度量,耦合强弱取决于...
  • 分析出解决问题所需要的步骤,然后用函数把这些步骤一步步实现,使用的时候再一个个的依次调用即可。 优点:性能高 缺点:相较于面向对象而言,不易维护,不易复用,不易扩展 适合于小型的项目 面向对象编程: 把...
  • 降低耦合

    千次阅读 多人点赞 2011-08-17 20:13:05
    按照软件工程学粗浅的理解,耦合就是程序中模块与模块间的关系的总和。上面的“模块”一词是一个模糊的概念,可以是一个变量、一个函数、一个类,或者是一个package(在大型软件项目中)。 显然,如果这样定义...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 192,129
精华内容 76,851
关键字:

编程的耦合问题