* 序言 |
写这篇博客之前,小编特意看了看之前自己写的有关设计模式的内容,当时刚刚接触设计模式,满心欢喜的希望自己可以有独特的认识,不过由于自己所接触内容的限制,当时理解仅仅停留在书面层次的概念中,不过每一次的成长都不是必然的,无论作用的大小,我相信每一次的接触和学习都是对自己有帮助的,欢迎大家指教!
近期在项目中,自己再一次接触到了工厂方法和抽象工厂,并且在迭代中体会他们的优缺点,当然难免会有些地方小编用词不当,希望路过的基友不吝指教。
* 工厂方法 |
工厂方法的特点:将产品创建的细节隐藏,生产单一的产品,她的优点是支持OCP(Open Closed Principle)原则,又熟悉了一下工厂方法的UML,如下:

在该项目中,涉及到物料DAO我们尽量的抽取,对于物料的操作,采用工厂方法涉及模式,方便我们在更换数据库时,对扩展开发。如下:

对于Dao的创建code自己便不再展示了,这里很贴合的用到了工厂方法。小编想说一下service和dao之间,其实这里也可以说是工厂方法,虽然manager只有一种实现方式,但是完全不影响我们日后的扩充,不过现在也没有这个必要。
private ItemDao itemDao=null;
//region 逻辑层创建itemDao的实现,由直接new具体对象,到配置文件读取,无完全优化--viola--2018年6月28日11:11:33
/**
* 构造函数中,创建itemdao
* 没有优化的
*/
public ItemManagerImpl() {
//调用工厂接口,向上转型
//引入配置文件
String className= XmlConfigRead.getInstance().getDaoFactory("item-dao-factory");
ItemDaoFactory itemDaoFactory=null;
try {
//装载到内存,实例化
itemDaoFactory=(ItemDaoFactory) Class.forName(className).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//创建对象
itemDao=itemDaoFactory.createItemDao();
}*/
//endregion
* 抽象工厂 |
上面这样的写法是没有问题的,不过当我们扩充另一种实现的service时,上面的大部分内容又要被我们再写一篇,这样有变动的时候需要修改的内容就会变得很多,代码的复用性显而易见。

这时我们的需求便不再是创建单一的产品了,我们是要创建一系列的产品,不光是物料,可能还会涉及到订单模块,我们需要有一个地方可以进行统一的创建,这便需要我们再网上抽象,工厂方法已经不能满足了。因此需要引入抽象工厂,往往我们使用抽象工厂时,都会有一个很好的小伙伴在,便是配置文件,为什么要用配置文件呢?我们可以思考一个问题,如果我们在使用中new 了一个对象,那么我们便是依赖的具体,如果想要依赖抽象,那要如果做呢?

//ItemManagerImpl 中
//region 逻辑层创建itemDao实现,这里建立抽象工厂,统一创建,配置--viola--2018-6-28 11:13:14
public ItemManagerImpl(){
itemDao= (ItemDao) BeanFactoryNew.GetInstance().getDaoObject("itemDao");
}
//BeanFactoryNew 中
package com.bjpowernode.drp.util;
import com.bjpowernode.drp.basedata.dao.ItemDao;
import com.bjpowernode.drp.basedata.manager.ItemManager;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import sun.security.jca.GetInstance;
import java.util.HashMap;
import java.util.Map;
/**
* 抽象工厂中的具体工厂,创建不同的产品
* 使用单例:
* Created by Viola on 2018/6/28.
*/
public class BeanFactoryNew {
private static BeanFactoryNew instance=new BeanFactoryNew();
public static BeanFactoryNew GetInstance(){
return instance;
}
//读取的配置文件
private final String beansConfigFile="beans-config.xml";
//承载配置文件
private Document doc;
//serviceMap
private Map serviceMap=new HashMap();
//daoMap
private Map daoMap=new HashMap();
/**
* 初始化,读取配置文件
*/
private BeanFactoryNew(){
//读取配置文件
try {
doc= new SAXReader().read(Thread.currentThread().getContextClassLoader().getResourceAsStream(beansConfigFile));
} catch (DocumentException e) {
e.printStackTrace();
throw new RuntimeException();
}
}
/**
* 根据产品编号取得service系列产品
* @param serviceId
* @return
*/
public synchronized Object getServiceObject(String serviceId){
//存在相关实例的话,返回
if (serviceMap.containsKey(serviceId)){
return serviceMap.get(serviceId);
}
//得到指定id节点对象
Element serviceElt=(Element) doc.selectSingleNode("//service[@id=\""+serviceId+"\"]");
//获得类名
String serviceClassName=serviceElt.attributeValue("class");
Object serviceClass=null;
//实例化
try {
serviceClass= Class.forName(serviceClassName).newInstance();
//放入map中
serviceMap.put(serviceId,serviceClass);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException();
}
return serviceClass;
}
/**
* 取得dao系列产品
* @param daoId
* @return
*/
public synchronized Object getDaoObject(String daoId){
//存在相关实例的话,返回
if (serviceMap.containsKey(daoId)){
return serviceMap.get(daoId);
}
//得到指定id节点对象
Element serviceElt=(Element) doc.selectSingleNode("//dao[@id=\""+daoId+"\"]");
//获得类名
String daoClassName=serviceElt.attributeValue("class");
Object daoClass=null;
//实例化
try {
daoClass= Class.forName(daoClassName).newInstance();
//放入map中
serviceMap.put(daoId,daoClass);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException();
}
return daoClass;
}
}
//配置文件beansConfigFile:中
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
<!--物料dao,oracle实现-->
<!--基于分层-->
<!--service-->
<service-class>
<service id="itemManager" class="com.bjpowernode.drp.basedata.manager.ItemManagerImpl"></service>
</service-class>
<!--Dao-->
<dao-class>
<dao id="itemDao" class="com.bjpowernode.drp.basedata.dao.ItemDao4OracleImpl"></dao>
</dao-class>
</beans>
* 原则 |
可能存在好多设计模式,我们使用的不是很多,也不是很清楚,个人认为是没有什么好担心的,小编认为重要的是我们明白他们背后的一些原则,这对我们平时的开发和设计中有很大的指导作用。
1. 开闭原则
a) 扩展开发,修改关闭
2. 里式代换原则
a) 子类可以代替父类
3. 依赖倒转原则
a) 面向抽象,非具体
4. 接口隔离原则
a) 通信窄,单独接口
5. 迪米特法则
a) 实体间的联系,尽可能小
6. 合成复用法则
a) 用合成和聚合方法,代替继承
* End |
本文中的方案也不是最完善,每一次都有收获就好,我的目标是比上一次好点点,每一次都可以进步一点点。
感谢您宝贵的阅读时间。