zoukankan      html  css  js  c++  java
  • Spring解耦和耦合

    程序中的耦合和解耦

    什么是程序的耦合

    耦合性(Coupling),也叫耦合度,是对模块间关联程度的度量。耦合的强弱取决于模块间接口的复杂性、调用模块的方式以及通过界面传送数据的多少。模块间的耦合度是指模块之间的依赖关系,包括控制关系、调用关系、数据传递关系。模块间联系越多,其耦合性越强,同时表明其独立性越差(降低耦合性,可以提高其独立性)。耦合性存在于各个领域,而非软件设计中独有的,但是我们只讨论软件工程中的耦合。

    总结:在软件工程中,耦合指的就是指对象之间的依赖关系。对象之间的依赖程度越高,耦合度就越高。对象之间的耦合越高,维护成本越高。因此对象的设计应使类和构件之间的耦合最小。

    降低程序之间的依赖程度,即降低程序之间的耦合度的过程就叫做解耦。

    例如:早期的Jdbc操作中,在注册数据库驱动时,为什么采用的是Class.forName的方式,而不是采用DriverManager.registerDriver的方式?

    public class TestJdbc {
      public static void main(String[] args) throws Exception {
        //1.注册数据库驱动
        // DriverManager.registerDriver( new Driver() );
        Class.forName("com.mysql.jdbc.Driver");
        //2.获取数据库连接
        //3.获取传输器
        //4.发送sql到服务器执行并返回执行结果
        //5.处理结果
        //6.释放资源
      }
    }
    

    除了DriverManager.registerDriver会导致驱动注册两次外,更重要的是,如果使用这种方式,JDBC程序就会依赖于数据库的驱动类(MySQL的Driver类),如果后期程序因数据量和性能原因升级到Oracle数据库,就需要修改程序源代码——重新导入新的驱动类,这会增加很多不必要的麻烦!

    而是用Class.forName方式注册驱动,这样的好处是Jdbc程序不再依赖具体的驱动类,即使删除(或不导入)mysql驱动包,程序依然可以编译(当然不可能运行,因为运行时肯定需要依赖驱动)。

    此时类中仅仅是将mysql驱动类的全限定类名写死在程序中(只是一个字符串),可以将这个字符串提取到配置文件中,后期可以通过修改配置文件(而不用修改程序代码)轻松的替换数据库产品。

    使用工厂模式解耦

    我们可以创建一个工厂, 使用工厂来创建对象. 而不是我们手动去new

    在maven的resource下创建配置文件

    EmpService=com.test.service.EmpServiceImpl
    EmpDao=com.test.dao.EmpDaoImpl
    

    编写工厂类

    package com.test.factory;
    
    import java.io.InputStream;
    import java.util.Properties;
    
    /**
     * 使用工厂+接口+配置文件 (降低)程序之间的耦合性(也就是以来成都)
     * 
     * 作用: 帮我们创建程序中所需要的对象
     * (而不是通过new的方式获取对象, 因为new对象会造成耦合性提升)
     * 目的: 当我们替换某一层(类)时, 不需要修改java源代码, 就可以实现
     * 
     * 工程: BeanFactory
     * 配置文件: config.properties (放在src/main/resource下)
     * 		配置文件中负责配置Service层的实现类和Dao层的实现类
     * 		也就是说, 配置的是哪一个实现类, 我们就获取哪一个实现类的示例
     * 		如果将来要替换实现类, 只需要修改配置文件中配置的实现类即可!
     * 
     * 接口: EmpService, EmpDao
     */
    public class BeanFactory {
    	
    	private static Properties prop = null;
    	static {
    		// 为prop进行初始化
    		prop = new Properties();
    		try {
    			// 加载config.properties文件, 获取指向该文件的流对象
    			// 通过当前类的字节码对象获取加载当前类的加载器
    			ClassLoader loader = BeanFactory.class.getClassLoader();
    			InputStream in = loader.getResourceAsStream("config.properties");
    			prop.load(in);
    			
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    	
    	/**
    	 * 根据接口名(EmpService, EmpDao) 获取该接口对应的子类实例
    	 */
    	public static Object getBean(String key) {
    		try {
    			// 通过key(接口名)获取该接口对应了类的全限定类名
    			String className = prop.getProperty(key);
    			// 通过子类的全限定类名, 获取该子类的字节码对象, 通过字节码对象获取类的实例
    			Object obj = Class.forName(className).newInstance();
    			return obj;
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		return null;
    	}
    }
    

    现在我们创建对象可以使用, 不用每次都去new, 大大降低了程序的耦合性

    private EmpService service = (EmpService) BeanFactory.getBean("EmpService");
    
  • 相关阅读:
    Jmeter设计压力测试场景&请求元件之并发场景设置&Jmeter查看压力测试结果&压力测试结果分析(二十九)
    Jmeter录制APP脚本(二十八)
    Jmeter优化web脚本&Jmeter回放web脚本和联调&Jmeter WEB脚本参数化(二十七)
    Jmeter结合badboy录制脚本(二十六)
    Jmeter录制WEB的原理(二十五)
    Jmeter实践:一粒云项目—Jmeter获取文件列表与下载接口串联测试及上传文件与下载接口之间的串联测试(二十四)
    Jmeter实践:一粒云项目—Jmeter完成文件的列表获取及JSON Extractor获取数组类型的数据及正则表达式获取数组类型的数据(二十三)
    Jmeter实践:一粒云项目—Jmeter完成文件下载及批量完成文件下载(二十二)
    Jmeter实践:一粒云项目—Jmeter完成文件上传及批量完成文件上传(二十一)
    Jmeter实践——新的项目介绍(二十)
  • 原文地址:https://www.cnblogs.com/zpKang/p/13176264.html
Copyright © 2011-2022 走看看