程序间的耦合-20.02.27

  • 编写jdbc的工程代码用于分析程序的耦合

    添加依赖
    <dependencies>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql - connec tor- java</artifactId>
      <version>5.1.7</version>
    </dependency>
    </ dependencies>
    
    
    //copy下来的代码,与下面项目不是同一个
    public class JdbcDemo1 {
    public static void main(String[] args) throws Exception{
    //1.注册驱动
    DriverManager.registerDriver(new com.mysql.jdbc.Driver());
    //2.获取连接
    Connection conn = DriverManager.getConnection( "jdbc :mysql://localhost:3307/mydb","root","980106WSK");
    //3.获取操作数据库的预处理对象
    PreparedStatement pstm = conn.prepareStatement("select * from account");
    //4.执行SQL,得到结果集
    ResultSet rs = pstm.executeQuery();
    //5.遍历结果集
    while(rs.next()){
    System.out.print1n(rs.getString("name"));
    }
    //6.释放资源
    rs.close() ;
    pstm.close();
    conn.close();
    
    
  • 编译期依赖
    将依赖注释掉程序报错

    Error: (14, 56) java :程序包com.mysql. jdbc不存在

    Compilatien conpleted with 1 ertor and 0 waringe in 2s 648ms(编译时遇到错误)

  • 程序的耦合和解耦的思路分析

    • 耦合 : 程序间的依赖关系
      • 类之间的依赖
      • 方法间的依赖
    • 解耦 : 降低程序间的依赖关系
    • 实际开发中 ,应该做到:
      • 编译期不依赖
      • 运行时才依赖
    • 解耦思路 :
      • 使用反射来创建对象,而避免使用new关键字
      • 通过读取配置文件来获取要创建的对象全限定类名
  • 曾经代码中的问题分拆

    private IitemsDao iitemsDao = new ItemsDaoImpl();
    
    IitemsService iitemsService = new ItemsServiceImpl();
    

    业务层调用持久层,表现层调用业务层,使用new关键字的依赖关系有很强的耦合性,使我们代码的独立性很差

  • 编写工厂类和配置文件

    • BeanFactory类
    /**
    * 一个创建Bean对象的工厂
    *
    * Bean:在计算机英语中,有可重用组件的含义。
    * JavaBean:用java语言编写的可重用组件。
    *         javabean >实体类
    *     它就是创建我们的service和dao对象的。
    *
    *     第一个:需要一个配置文件来配置我们的service和dao
    *             配置的内容:唯一标识=全限定类名 (key=value)
    *     第二个:通过读取配置文件中配置的内容,反射创建对象
    *     我的配置文件可以是xml也可以是properties
    */
    public class BeanFactory{
        
    }
    
    • bean.properties配置文件
    itemsDao=com.qfetu.dao.impl.ItemsDaoImpl
    itemsService=com.qfetu.service.impl.ItemsServiceImpl
    
  • 工厂模式解耦

    • BeanFactory类
    /**
     * 一个创建Bean对象的工厂
     *
     * Bean:在计算机英语中,有可重用组件的含义。
     * JavaBean:用java语言编写的可重用组件。
     *        javabean >实体类
     *    它就是创建我们的service和dao对象的。
     *
     *    第一个:需要一个配置文件来配置我们的service和dao
     *            配置的内容:唯一标识=全限定类名 (key=value)
     *    第二个:通过读取配置文件中配置的内容,反射创建对象
     *    我的配置文件可以是xml也可以是properties
     */
    public class BeanFactory {
        //定义一个Properties对象
        private static Properties properties;
    
        //使用静态代码块为properties对象赋值
        static {
            try {
                //实例化对象
                properties = new Properties();//有些耦合是无法避免的,我们不能做到完全消除
    
                //获取properties文件的流对象
                //InputStream is = new FileInputStream(); 这里不要用FileInputStream,而是使用类加载器的形式
                InputStream is = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
    
                properties.load(is);
            } catch (Exception e) {
               throw new ExceptionInInitializerError("初始化properties失败");//这里抛出一个初始化异常,Error
            }
        }
    
        /**
         * 根据Bean的名称获取bean对象
         * @param beanName
         * @return
         */
        public static Object getBean(String beanName){
            Object bean = null;
            try {
                String beanPath = properties.getProperty(beanName);
                bean = Class.forName(beanPath).newInstance();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return bean;
        }
    }
    
    //IitemsService iitemsService = new ItemsServiceImpl();
            IitemsService iitemsService = (IitemsService)BeanFactory.getBean("itemsService");
    
     //private IitemsDao iitemsDao = new ItemsDaoImpl();
        private IitemsDao iitemsDao = (IitemsDao)BeanFactory.getBean("itemsDao");
    
  • 分析工厂模式中的问题并改造

    • 多例
       for (int i = 0; i < 5; i++) {
                IitemsService iitemsService = (IitemsService)BeanFactory.getBean("itemsService");
                System.out.println(iitemsService);
            }
    
打印结果

此时的对象是多例的,对象被创建多次,执行效率没有单例对象高

  • 单例

    只被创建一次,从而类中的成员也就只会初始化一次,有线程问题,但是在Service和Dao层是没有类成员的,所以不存在线程问题

bean = Class.forName(beanPath).newInstance();//每次都会调用默认构造函数创建对象
  • 分析

    通过对单例的分析,显然并不需要多例,只需要每一次都是同一个对象就够了,所以对这个方法进行调整,调整的前提是对象只能newInstance()一次.如果你创建之后不存起来,根据java的垃圾回收机制,它会在长时间不用时被回收,当下一次再使用时,就没有了,所以需要在对象创建出来后马上存起来

  • 工厂模式解耦的升级版

    • 修改后的BeanFactory类
    /**
     * 一个创建Bean对象的工厂
     *
     * Bean:在计算机英语中,有可重用组件的含义。
     * JavaBean:用java语言编写的可重用组件。
     *        javabean >实体类
     *    它就是创建我们的service和dao对象的。
     *
     *    第一个:需要一个配置文件来配置我们的service和dao
     *            配置的内容:唯一标识=全限定类名 (key=value)
     *    第二个:通过读取配置文件中配置的内容,反射创建对象
     *    我的配置文件可以是xml也可以是properties
     */
    public class BeanFactory {
        //定义一个Properties对象
        private static Properties properties;
    
        //定义一个Map,用于存放我们要创建的对象,我们把它称之为容器
        private static Map<String,Object> beans;
    
        //使用静态代码块为properties对象赋值
        static {
            try {
                //实例化对象
                properties = new Properties();//有些耦合是无法避免的,我们不能做到完全消除
    
                //获取properties文件的流对象
                //InputStream is = new FileInputStream(); 这里不要用FileInputStream,而是使用类加载器的形式
                InputStream is = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
                properties.load(is);
    
                //实例化容器
                beans = new HashMap<String,Object>();
                // 取出配置文件中所有的Key
                Enumeration keys = properties.keys();
                // 遍历枚举
                while (keys.hasMoreElements()){
                    // 取出每个Key
                    String key = keys.nextElement().toString();
                    // 根据key获取value
                    String beanPath = properties.getProperty(key);
                    //反射创建对象
                    Object value = Class.forName(beanPath).newInstance();
                    //把key和value存入容器中
                    beans.put(key,value);
                }
            } catch (Exception e) {
               throw new ExceptionInInitializerError("初始化properties失败");//这里抛出一个初始化异常,Error
            }
        }
    
        /**
         * 根据bean的名称获取对象
         * @param beanName
         * @return
         */
        public static Object getBean(String beanName){
            return beans.get(beanName);
        }
    
      /*  *//**
         * 根据Bean的名称获取bean对象
         * @param beanName
         * @return
         *//*
        public static Object getBean(String beanName){
            Object bean = null;
            try {
                String beanPath = properties.getProperty(beanName);
                bean = Class.forName(beanPath).newInstance();   //每次都会调用默认构造函数创建对象
            } catch (Exception e) {
                e.printStackTrace();
            }
            return bean;
        }*/
    }
    
打印结果

在使用Map将对象存进去之后会发现,后续使用后就不需要再反复创建

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容