简单工厂模式:
简单工厂模式是创建型模式,创建型模式顾名思义,也就是说在创建对象的时候,遇到了瓶颈才会选择的设计模式。那么该什么情况使用呢。
简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建并且返回哪一个产品类(这些产品类继承自一个父类或接口)的实例。
那么也就是说:
1、有已知的产品类
2、你无法准确的知道编译哪个产品类
3、需要在运行时决定创建哪个产品类
4、产品类不多
很明显看出,在创建对象上的灵活性高,但是工厂类只能创建可能会使用到的产品类,假如新添了产品类就得修改工厂类,这样就会违反开闭原则。
说明:从 策略模式 到 简单工厂模式(项目最初用策略模式,但遇到一些问题,下面会讲到。后来为了解决问题,改用简单工厂模式)
业务场景:
本项目是管理硬件操作的后台管理系统,后台系统发一些指令到硬件,硬件返回json数据,后台解析数据,再根据数据返回给前端操作结果,当时首选使用策略模式,根据硬件返回的类型创建不同的类,不同的类进行相应的数据封装,封装后给前端。(比如不同的code,不同的message,不同的object啊);然后在发送的时候,用反射根据类型生成具体封装类。(整个过程用websocket连接,我们后台系统作为客户端发送指令到硬件服务端;同时后台也作为服务端将操作结果发送给浏览器)
例子:
硬件返回的类型为:end
接口类:
public interface ReturnResult{
public Result returnResult();
}
具体业务类
public class End implements ReturnResult{
public Result returnResult(){
int code = 200;
String message = "成功";
List<String> object = null;
return Result(code,message,object);
}
}
策略类:
public clas ReturnResultStrategy{
//持有的具体策略的对象
private ReturnResult returnResult;
/**
* 构造函数,传入一个具体策略对象
* @param returnResult 具体策略对象
*/
public ParamValidateStrategy(ReturnResult returnResult) {
super();
this.returnResult = returnResult;
}
/**
* 策略方法
*/
public Result retResult(){
return retResult.returnResult();
}
}
调用地方:
//获取到的类型 type,从硬件来
String type = "";
//反射生成类
Class<?> forName = Class.forName("com.utils."+type);
//实例化对象
Object obj = forName.newInstance();
ReturnResultStrategy returnResultStrategy = new ReturnResultStrategy((ReturnResult) obj);
returnResultStrategy.retResult();
遇到的问题 || 为何改用简单工厂模式?:
在websocket类中,收到硬件发送过来的消息时,根据类型制定具体策略类时报null.
为什么报空呢?因为在某几个策略类中,注入了接口,并通过注入的接口调用了实现类的方法。这样我们就将自己的类交给了 Spring 帮我们管理。而在使用策略类时,是用的new对象。new对象意思就是我们自己管理类。这样一来,我们自己管理类中又让 spring 帮我们管理。那到底谁管理,类就懵逼了。就好像,周末的时候爸爸帮你报了吉他班,妈妈帮你报了舞蹈班;周末了,两个班的老师都打电话让你去学习,是不是很懵逼啊,到底去哪里呢,去吉他班,舞蹈班老师找不到你,只好给你妈妈报空null;去舞蹈班,吉他班老师又会给你爸爸报空null。只要有一个为空,回家都要挨揍,那你到底去哪里呢,横竖都挨揍,算了哪里都不去了,离家出走吧!
经过一系列吹牛逼,最终选择了简单工厂模式,都交给spring吧。
简单工厂:
首先写一个工厂类:
@Component
public class ReturnResultFactory {
@Autowired
private Map<String, ReturnResult> context = new ConcurrentHashMap<>();
public ReturnResult getDataViewClass(String rquestTypeStr) {
return this.context.get(rquestTypeStr);
}
}
具体业务类,实现的接口还是上面的接口
重点在 @Component("end") 这个注解。springq启动的时候,spring的工厂类就会创建对象,用map封装,在这里key就是@Component的value值,值就是 End 这个类
@Component("end")
public class End implements ReturnResult {
@Autowired
private ResponseDataParse responseDataParse;
/**
*以下代码可以不用理解,只需要知道调用了注入进来的接口中的方法就ok了
**/
@Override
public ResponseViewData returnRespViewData(String rquestTypeStr,String taskId,String data){
if(rquestTypeStr.equals(WSRequestType.TAKE_BOX.getValue())){
return responseDataParse.parseTakeBoxData(data);
}else if(WSRequestType.STORE_BOX.getValue().equals(rquestTypeStr)){
return responseDataParse.insertData(data);
}
return null;
}
}
调用的地方:
@ClientEndpoint()
@Component
public class WSClient {
@Resource
ResponseViewDataStreategyFactory factory;
public static WSClient wsClient;
@PostConstruct
public void init() {
wsClient = this;
}
@OnMessage
public void onMessage(String message){
//message转成json对象后从中获取type
String type = "";
ReturnResult returnResult = wsClient.factory.getDataViewClass(type);
}
}
区别总结
从上面的描述总结出,在运行时,两者都是通过传入参数进行配置,简单工厂模式则是选择创建出需要的对象,而策略模式则是配置出需要的行为算法。一个是对象创建,另一个是行为算法的替换。