首先我们先了解一下什么是程序的耦合,耦合指的是程序间的依赖关系。那么解耦的意思就是要降低程序间的依赖关系。在我们实际开发中:应该做到,编译期不依赖,运行时才依赖。
好了上面废话那么多,我们先来看一段程序。
/**
* @ClassName: AccountServiceImpl
* @author: benjamin
* @version: 1.0
* @description: 账户业务层接口的实现类
* @createTime: 2019/07/24/17:10
*/
public class AccountServiceImpl implements IAccountService {
private IAccountDao accountDao = new AccountDaoImpl();
public void saveAccount(){
System.out.println("业务层保存账户。。。");
}
}
可以看到,此时业务层的代码调用了持久层的实体类,如果我们此时没有持久层实现类,那么编译不能通过。这种编译期间依赖关系,我们应该杜绝。
工厂模式解耦
在实际开发中我们可以把三层的对象都使用配置文件配置起来,当启动服务器应用加载的时候,让一个类中的方法通过读取配置文件,把这些对象创建出来并存起来。在接下来的使用的时候,直接拿过来用就好了。那么,这个读取配置文件, 创建和获取三层对象的类就是工厂。
我们先来看一下项目的结构:
-
创建maven工程;
-
创建业务层接口和实现类
/** * 账户的业务层接口 * @ClassName: IAccountService * @author: benjamin * @createTime: 2019/07/24/17:08 */ public interface IAccountService { /** * 模拟保存账户 */ void saveAccount(); } /** * @ClassName: AccountServiceImpl * @author: benjamin * @version: 1.0 * @description: 账户业务层接口的实现类 * @createTime: 2019/07/24/17:10 */ public class AccountServiceImpl implements IAccountService { private IAccountDao accountDao = new AccountDaoImpl(); public void saveAccount(){ System.out.println("业务层保存账户。。。"); accountDao.saveAccount(); } }
-
创建持久层接口和实现类
/** * 账户的持久层接口 * @ClassName: IAccountDao * @author: benjamin * @createTime: 2019/07/24/17:07 */ public interface IAccountDao { /** * 模拟保存账户 */ void saveAccount(); } /** * @ClassName: AccountDaoImpl * @author: benjamin * @version: 1.0 * @description: 账户的持久层实现类 * @createTime: 2019/07/24/17:10 */ public class AccountDaoImpl implements IAccountDao { public void saveAccount(){ System.out.println("保存了账户"); } }
-
创建表现层
/** * @ClassName: Client * @author: benjamin * @version: 1.0 * @description: 模拟一个表现层,用于调用业务层 * @createTime: 2019/07/24/17:08 */ public class Client { public static void main(String[] args) { // 耦合 IAccountService as = new AccountServiceImpl(); System.out.println(as); as.saveAccount(); } }
可以看到,现在程序中表现层与业务层,表现层和持久层出现了耦合,我们应该进行避免,下面采用工厂模式来降低耦合。
-
创建一个bean.properties文件
accountService=com.ben.service.impl.AccountServiceImpl accountDao=com.ben.dao.impl.AccountDaoImpl
-
创建bean对象的工厂,它就是创建我们的service和dao对象的。
Bean:在计算机英语中,有可重用组件的含义。
JavaBean:用java语言编写的可重用组件。
javabean > 实体类- 需要一个配置文件来配置我们的service和dao配置的内容:唯一标识=全限定类名(key=value);
- 通过读取配置文件中配置的内容,反射创建对象。配置文件可以是xml也可以是properties(Spring框架中使用的是xml文件),在本次案例中我们使用properties。
/** * @ClassName: BeanFactory * @author: benjamin * @version: 1.0 * @description: bean工厂 * @createTime: 2019/07/24/17:08 */ public class BeanFactory { //定义一个Properties对象 private static Properties props; //定义一个Map,用于存放我们要创建的对象。我们把它称之为容器 private static Map<String, Object> beans; //使用静态代码块为Properties对象赋值 static{ try { //实例化对象 props = new Properties(); //获取properties文件的流对象 InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties"); props.load(in); //实例化容器 beans = new HashMap<String,Object>(); //取出配置文件中所有的Key Enumeration keys = props.keys(); //遍历枚举 while (keys.hasMoreElements()){ //取出每个Key String key = keys.nextElement().toString(); //根据key获取value String beanPath = props.getProperty(key); //反射创建对象 Object value = Class.forName(beanPath).newInstance(); //把key和value存入容器中 beans.put(key,value); } }catch(Exception e){ throw new ExceptionInInitializerError("初始化properties失败!"); } } /** * 根据bean的名称获取对象 * @param beanName * @return Object */ public static Object getBean(String beanName){ return beans.get(beanName); } }
-
修改表现层文件
public class Client { public static void main(String[] args) { for(int i=0;i<5;i++) { IAccountService as = (IAccountService) BeanFactory.getBean("accountService"); System.out.println(as); as.saveAccount(); } } }