工厂设计模式(Factory Design Pattern)

142 阅读3分钟

参考资料

image.png

应用场景

  • 代码中存在 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 一下就可以,而是要组合其他类对象,做各种初始化操作的时候,我们推荐使用工厂方法模式,将复杂的创建逻辑拆分到多个工厂类中,让每个工厂类都不至于过于复杂。


抽象工厂

image.png

一个对象族(或是一组没有任何关系的对象)都有相同的约束,则可以使用抽象工厂 例:

  • 系统日志对象、业务日志对象...
  • 文本编辑器、图片处理器...

上面的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