程序的耦合和解耦

什么是程序的耦合?

  • 耦合性(Coupling),也叫耦合度,是对模块间关联程度的度量。耦合的强弱取决于模块间接 口的复杂性、调用模块的方式以及通过界面传送数据的多少。模块间的耦合度是指模块之间 的依赖关系,包括控制关系、调用关系、数据传递关系。模块间联系越多,其耦合性越强, 同时表明其独立性越差(降低耦合性,可以提高其独立性)。耦合性存在于各个领域,而非软 件设计中独有的,但是我们只讨论软件工程中的耦合。
  • 在软件工程中, 耦合指的就是就是对象之间的依赖性。对象之间的耦合越高,维护成本越 高。因此对象的设计应使类和构件之间的耦合最小。软件设计中通常用耦合度和内聚度作为 衡量模块独立程度的标准。

耦合的分类

  • 内容耦合。公共耦合。外部耦合 。控制耦合 。标记耦合 。数据耦合。非直接耦合 。

内聚与耦合

  • 内聚标志一个模块内各个元素彼此结合的紧密程度,它是信息隐蔽和局部化概念的自然扩 展。 内聚是从功能角度来度量模块内的联系,一个好的内聚模块应当恰好做一件事。它描述 的是模块内的功能联系。耦合是软件结构中各模块之间相互连接的一种度量,耦合强弱取决 于模块间接口的复杂程度、进入或访问一个模块的点以及通过接口的数据。 程序讲究的是低 耦合,高内聚。就是同一个模块内的各个元素之间要高度紧密,但是各个模块之间的相互依 存度却要不那么紧密。
  • 内聚和耦合是密切相关的,同其他模块存在高耦合的模块意味着低内聚,而高内聚的模块意 味着该模块同其他模块之间是低耦合。在进行软件设计时,应力争做到高内聚,低耦合。

传统JDBC存在的耦合性问题及解耦思想

问题代码

try {
	//1,注册驱动 
	DriverManager.registerDriver(new Driver()); 
	//2,获取连接 
	Connection connection = DriverManager.getConnection("jdbc:mysql:///test", "root", "root"); 
	//3,获取执行sql对象 
	PreparedStatement statement = connection.prepareStatement("update tb_user set username = ? where id = ?"); 
	//4,执行sql 
	statement.setString(1,"hahaha"); statement.setLong(2,1); 
	//5,释放资源 
	connection.close(); 
	statement.close(); 
} catch (Exception e) { 
	e.printStackTrace(); 
}

分析

  • 实际开发中,解耦的本质
    将编译期依赖变更为运行时依赖

  • 解耦思路
    使用反射创建对象,尽量少使用new关键字 使用配置文件存储要创建对象的全类名

之前三层架构中存在的耦合性问题及解决方案

问题代码

//Web层 
public class UserServlet extends HttpServlet{
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
		UserService userService = new UserServiceImpl();
		 ...... 
	 } 
 }
 
//Service层 
public class UserServiceImpl implements UserService { 
	public void login(User user){ 
		UserDao userDao = new UserDaoImpl(); 
		...... 
	} 
}

//Dao层 
public class UserDaoImpl implements UserDao { 
	public void login(User user){ 
		...... 
	} 
}

解决思路1
使用工厂模式、反射、xml配置文件

public class MyApplicationContext { 
	private String path; 
	private Map<String,String> map = new HashMap<>(); 
	public MyApplicationContext1() { 
	}

	public MyApplicationContext1(String path) { 
		this.path = path; 
		parseXML(path); 
	}

private void parseXML(String path) { 
	SAXReader saxReader = new SAXReader(); 
	try {
		Document document =
		saxReader.read(MyApplicationContext1.class.getClassLoader().getResourceAsStream( path)); 
		Element beansEle = document.getRootElement(); 
		List<Element> beanEles = beansEle.elements(); 
		for (Element beanEle : beanEles) { 
			String id = beanEle.attributeValue("id"); 
			String className = beanEle.attribute("class").getValue(); 
			map.put(id,className); 
			} 
		} catch (Exception e) { 
		e.printStackTrace(); 
		} 
	}

	public Object getBean(String id){ 
		try {
			return Class.forName(map.get(id)).newInstance(); 
		} catch (Exception e) { 
			e.printStackTrace(); 
		}
		return null; 
	} 
}

代码测试

public class Demo01 { 

	public static void main(String[] args) { 
		MyApplicationContext applicationContext = new MyApplicationContext("applicationContext.xml"); 
		Object userService1 = applicationContext.getBean("userService"); 
		Object userService2 = applicationContext.getBean("userService"); 
		System.out.println(userService1 == userService2); 
		}
}

能够创建出对象,但是测试结果为false,说明由工厂类创建出来的实例是多例的!

  • 思路1存在的问题
    由工厂类创建出来的实例是多例的,如果改成单例,会提高效率
public class MyApplicationContext { 
	private String path; 
	private Map<String,Object> map = new HashMap<>(); 

	public MyApplicationContext() { 
	}
	
	public MyApplicationContext(String path) { 
		this.path = path; 
		parseXML(path); 
	}

	private void parseXML(String path) { 
		SAXReader saxReader = new SAXReader(); 
		try {
			Document document = saxReader.read(MyApplicationContext.class.getClassLoader().getResourceAsStream(p ath)); 
			Element beansEle = document.getRootElement(); 
			List<Element> beanEles = beansEle.elements(); 
			for (Element beanEle : beanEles) { 
				String id = beanEle.attributeValue("id"); 
				String className = beanEle.attribute("class").getValue(); 
				Object obj = Class.forName(className).newInstance(); 
				map.put(id,obj); 
			} 
		} catch (Exception e) { 
			e.printStackTrace(); 
		} 
	}

	public Object getBean(String id){ 
		return map.get(id); 
	} 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值