使用工厂模式--(反射+配置文件)的设计思路降低耦合度

工厂方法(Factory Method)模式

概念:
在创建类的时候,通常可以同时定义多个构造函数,然后利用他们创建类的实例,然而有些时候,客户并不关心对象究竟是从哪个类里面创建而来的,只需要某个对象即可。

工厂方法模式的意图:
定义一个用于创建对象的接口,并控制返回哪个类的实例

注意工厂模式进一步扩展将在后续进行补充,并不作为本小结重点内容

耦合性

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

注意:耦合与内聚进一步解释将在后续进行补充,并不作为本小结重点内容

案例;
使用三层架构的方式(只是用来说明)来阐述为什么要降低耦合度

  1. dao层
public interface UserDao {
    void findAll();
}
public class UserDaoImpl implements UserDao {
    @Override
    public void findAll() {
        System.out.println("dao运行了");
    }
}
  1. service层
public interface UserService {
    void findAll();
}
import com.chinasoft.service.UserService;

public class UserServiceImpl implements UserService {
    @Override
    public void findAll() {
        System.out.println("业务层运行了");

    }

}

web层

import java.io.IOException;
public class UserWeb {
    public static void main(String[] args) throws ClassNotFoundException, IOException, InstantiationException, IllegalAccessException {
        UserService userService=new UserServiceImpl();
        UserDao userDao=new UserDaoImpl();
        userService.findAll();
        userDao.findAll();
    }
}

由上述源码我们可以看出,每次当我们执行UserDaoImpl或者UserServiceImpl里的方法的时候,我们需要创建new一个UserDaoImpl对象或者UserServiceImpl,但是对于程序本身来说,我们的目的是需要使用这个类里面的方法,对于如何创建、几时创建这个类的对象,我们并不关心。同时,如果我们不创建这个对象,那么我们就无法进行下一步的操作,即无法:userService.findAll(); 在编译器就会报错。这是我们不愿意看到的,我们希望如果有错,在运行期报错而不是编译期。

降低耦合度的思想:

  •      1.利用反射创建对象,避免了使用new关键字
    
  •      2.通过读取配置文件来获取需要的创建的对象的全限定类名
    

bean.properties配置文件:

userService=com.chinasoft.service.impl.UserServiceImpl
userDao=com.chinasoft.dao.impl.UserDaoImpl

BeanFactory:

import java.io.IOException;
import java.util.*;

/**
 * 该类的作用:一个创建Bean对象的工厂类
 * 创建servive和dao对象
 */
 
public class BeanFactory {
    protected  static Properties pro;//定义一个用于接收properties对象的变量
    protected static Map<String,Object> map;//用于存储配置文件里面的对象名和其全限定类名


    //静态块在new对象之前就会执行,而且一个类在第一次被使用的时候会被加载,
    //然后在整个应用程序的生命周期当中不会再次被加载了,就加载这一次。
    static {
        try {
        //1.读取properties文件
            pro=new Properties();
            pro.load(BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties"));
        //2.获取properties里面的所有Key值
            Enumeration<Object> keys=pro.keys();
            map=new HashMap<>();//初始化map对象
            //判断是否有下一个元素
            while(keys.hasMoreElements()){
            	//nextElement()取出下一个元素
                String key=keys.nextElement().toString();
                //利用反射动态的创建一个对象
                Object bean=Class.forName(pro.getProperty(key)).newInstance();
                //将该对象放入map中
                map.put(key,bean);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

	//提供一个方法,用于获取"工厂"中的对象
    public static Object getBean(String beanName){
        return map.get(beanName);
    }
}

修改后的UserWeb:

public class UserWeb {
    public static void main(String[] args) throws ClassNotFoundException, IOException, InstantiationException, IllegalAccessException {
        UserService userService= (UserService) BeanFactory.getBean("userService");
        UserDao userDao= (UserDao) BeanFactory.getBean("userDao");
        userDao.findAll();
        userService.findAll();
    }
}

我们可以看出,在这里我们并没有使用new来创建对象,而是直接从工厂中取,这时候可能就会有人会问,只不过是换了一个地方new 对象,但是,如果我们此时这个地方写的参数不是userService或者userDao(即写的不是配置文件里的key值),那么程序一样不会在编译时期出错,这就是使用工厂模式–(反射+配置文件)设计的好处。


版权声明:本文为m0_56981185原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。