什么是工厂方法模式
属于创建型模式,又称多态性工厂模式。在工厂方法模式中,核心的工厂类不再负责所有的实例创建,而是将具体的创建工作交给子类工厂去做,核心工厂类成为一个抽象工厂角色,仅定义接口。
工厂方法模式使用场景
创建对象需要大量重复的代码
客户端(应用层)不依赖于产品类实例如何被创建、被实现等细节
工厂方法模式示例
还是通过简单工厂方法模式示例场景说明一下工厂方法模式的写法。
要求:根据不同的请求类型(read、write、delete、execute)选择不同的helper帮助构建不同的请求对象。
工厂方法模式不再是通过RequestHelperFactory创建所有的Helper实例,而是将RequestHelperFactory定义成接口,给每一种RequestHelper的创建定义一个实现RequestHelperFactory的工厂类。RequestHelperFactory不再负责创建Helper实例,而是由其子类负责创建。
//定义RequestHelperFactory接口
public interface RequestHelperFactory{
RequestHelper createHelper();
}
//ReadRequestHelperFactory
public class ReadRequestHelperFactory implements RequestHelperFactory{
@Override
public RequestHelper createHelper(){
return new ReadRequestHelper();
}
}
//WriteRequestHelperFactory
public class WriteRequestHelperFactory implements RequestHelperFactory{
@Override
public Request createHelper(){
return new WriteRequestHelper();
}
}
//DeleteRequestHelperFactory
public class DeleteRequestHelperFactory implements RequestHelperFactory{
@Override
public Request createHelper(){
return new DeleteRequestHelper();
}
}
//ExecuteRequestHelperFactory
public class ExecuteRequestHelperFactory implements RequestHelperFactory{
@Override
public Request createHelper(){
return new ExecuteRequestHelper();
}
}
//客户端应用
public Request createRequest(Command command){
String type = command.getType();
RequestHelperFactory requestHelperFactory= null;
if("read".equals(type)){
requestHelperFactory= new ReadRequestHelperFactory ();
}else if("writer".equals(type)){
requestHelperFactory= new WriteRequestHelperFactory ();
}else if("delete".equals(type)){
requestHelperFactory= new DeleteRequestHelperFactory ();
}else if("execute".equals(type)){
requestHelperFactory= new ExecuteRequestHelperFactory ();
}
RequestHelper = requestHelperFactory.createHelper();
return RequestHelper.createRequest();
}
以上就是工厂方法模式的实现,如果需要增加一种请求,增加相应的HelperFactory和Helper即可,工厂方法模式比简单工厂模式更符合开闭原则。但是上面客户端应用代码中,Helper的创建和Request的创建耦合在一起,这里可以通过给HelperFactory的创建再加一个简单工厂,解耦工厂的创建。
public class RequestHelperFactoryContainer{
private static final Map<String,RequestHelperFactory> cacheHelper = new HashMap<>();
static{
cacheHelper.put("read",new ReadRequestHelperFactory());
cacheHelper.put("write",new WriteRequestHelperFactory());
cacheHelper.put("delete",new DeleteRequestHelperFactory());
cacheHelper.put("execute",new ExcuteRequestHelperFactory());
}
public static RequestHelperFactory createHelperHelper(String type){
if(StringUtils.isEmpty(type)){
return new IllegalArgumentException("...");
}
return cacheHelper.get(type.toLowerCase());
}
}
//客户端应用
public Request createRequest(Command command){
String type = command.getType();
RequestHelperFactory requestHelperFactory= RequestHelperFactoryContainer.createHelperHelper(type);
RequestHelper = requestHelperFactory.createHelper();
return RequestHelper.createRequest();
}
当对象的创建逻辑比较复杂,不只是简单的 new 一下就可以,而是要组合其他类对象,做各种初始化操作的时候,推荐使用工厂方法模式,将复杂的创建逻辑拆分到多个工厂类中,让每个工厂类都不至于过于复杂。而使用简单工厂模式,将所有的创建逻辑都放到一个工厂类中,会导致这个工厂类变得很复杂。除此之外,在某些场景下,如果对象不可复用,那工厂类每次都要返回不同的对象。如果我们使用简单工厂模式来实现,就只能选择第一种包含 if 分支逻辑的实现方式。如果我们还想避免烦人的 if-else 分支逻辑,这个时候,也推荐使用工厂方法模式。
其实不知道大家有没有发现,只要产品的创建够复杂,我们可以抽象不止一层工厂,如果将Request看作最终产品,RequestHelper是工厂,如果将RequestHelper看作产品,RequestHelperFactory是工厂,这里就抽象了两级工厂。而且结合工厂方法和简单工厂方法可以有效简化客户端的调用。