• 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");
    
  • 相关阅读:
    唐寅 《桃花庵歌》
    asp.net 后台隐藏div
    dataset的用法
    C#中的DateTime类型加减
    discuz! x2.5 文章添加分享按钮
    asp.net学习小网站
    table固定行和表头
    aspx.net开源的画图组件
    Global.asax详解
    int.Parse() int.TryParse
  • 原文地址:https://www.cnblogs.com/zpKang/p/13176264.html
Copyright © 2020-2023  润新知