参考资料
应用场景
- 代码中存在 if-else 分支判断,动态地根据不同的类型创建不同的对象。
- 尽管我们不需要根据不同的类型创建不同的对象,但是,单个对象本身的创建过程比较复杂,比如要组合其他类对象,做各种初始化操作。
工厂模式实现方式
简单/静态工厂
第一种
public class BeanCreateFactory{
public static Bean createBean(String condition){
Bean bean = null;
if ("aa".equalsIgnoreCase(condition)){
bean = new aaBean();
}else if ("bb".equalsIgnoreCase(condition)){
bean = new bbBean();
}else if ("cc".equalsIgnoreCase(condition)){
bean = new ccBean();
}
return bean;
}
}
第二种
public class BeanCreateFactory{
private static final Map<String,Bean> cachedBean = new HashMap();
static{
cachedBean.put("aa",new aaBean());
cachedBean.put("bb",new bbBean());
cachedBean.put("cc",new ccBean());
}
public static Bean createBean(String condition){
if(condition == null || condition.isEmpty()){
return null;
}
Bean bean = cachedBean.get(condition.toLowerCase());
return parser;
}
}
相比较两种
第一种每次都要创建bean,第二种事先把bean缓存在map中。
如果bean可以复用,为了节省内存和对象创建的时间,可以将bean事先创建好缓存起来。
尽管简单工厂模式的代码实现中,有多处 if 分支判断逻辑,违背开闭原则,但权衡扩展性和可读性,这样的代码实现在大多数情况下(比如,不需要频繁地添加 parser,也没有太多的 parser)是没有问题的。
工厂方法
public interface BeanCreateFactory{
Bean createBean();
}
public class aaBeanCreateFactory implements{
@Override
public Bean createBean(){
return new aaBean();
}
}
public class bbBeanCreateFactory implements{
@Override
public Bean createBean(){
return new bbBean();
}
}
public class ccBeanCreateFactory implements{
@Override
public Bean createBean(){
return new ccBean();
}
}
public class CreateBean{
public Bean create(String condition){
BeanCreateFactory beanCreateFactory = BeanCreateFactoryMap.getBeanFactory(condition);
if(beanCreateFactory == null){
throw new Exception("Bean Factory is not allow to be empty");
}
Bean bean = beanCreateFactory.createBean();
return bean;
}
}
public class BeanCreateFactoryMap{
private static final Map<String,Bean> cachedBeanFactories = new HashMap();
static{
cachedBeanFactories.put("aa",new aaBeanCreateFactory());
cachedBeanFactories.put("bb",new bbBeanCreateFactory());
cachedBeanFactories.put("cc",new ccBeanCreateFactory());
}
public static BeanCreateFactory getBeanFactory(String condition){
if(condition == null || condition.isEmpty()){
return null;
}
BeanCreateFactory beanCreateFactory = cachedBeanFactories.get(condition.toLowerCase());
return BeanCreateFactory;
}
}
当我们需要添加新的bean的时候,我们只需要创建新的Bean类和BeanCreateFactory类,并且在 BeanCreateFactoryMap类中,将新的BeanCreateFactory对象添加到cachedBeanFactories中即可。代码的改动非常少,基本上符合开闭原则。
实际上,对于大多数应用场景来说,工厂模式需要额外创建诸多 Factory 类,也会增加代码的复杂性,而且,每个 Factory 类只是做简单的 new 操作,功能非常单薄(只有一行代码),也没必要设计成独立的类,所以,在这个应用场景下,简单工厂模式简单好用,比工厂方法模式更加合适。
当对象的创建逻辑比较复杂,不只是简单的 new 一下就可以,而是要组合其他类对象,做各种初始化操作的时候,我们推荐使用工厂方法模式,将复杂的创建逻辑拆分到多个工厂类中,让每个工厂类都不至于过于复杂。
抽象工厂
一个对象族(或是一组没有任何关系的对象)都有相同的约束,则可以使用抽象工厂 例:
- 系统日志对象、业务日志对象...
- 文本编辑器、图片处理器...
上面的Bean定义的太过笼统,假如要创建一个日志Logger对象,针对业务的日志对象,针对系统的日志对象...
每个类型都要编写Factory,3个变6个...
抽象工厂的诞生就是为了应对这种复杂的场景。
public interface LoggerCreateFactory{
BizLogger createBizLogger();
SysLogger createSysLogger();
}
public class BizLoggerCreateFactory{
@Override
public BizLogger create(){
return new BizLogger();
}
}
public class SysLoggerCreateFactory{
@Override
public SysLogger create(){
return new SysLogger();
}
}
//省略下面两个类的代码
//CreateLogger
//LoggerCreateFactoryMap