1. 前言
工厂方法模式,定义一个用于创建对象的接口,让子类决定实例化哪个类,工厂方法使一个类的实例化延迟到其子类。
什么意思呢?我们知道,在简单工厂模式中,所有对象的实例化都是在一个工厂类中完成,这样带来的问题就是每次增加新的产品类都必须要修改工厂类,这不符合开闭原则。
如何改良呢?工厂方法模式给出了答案,每一个具体对象的创建不再只由一个工厂完成,每一种类型的对象都有属于它自己的工厂,大家各司其职,互不干扰。
2. 实现
上一篇简单工厂模式的文章中,我们举了手机代工厂的例子,那么这一篇也在这个基础上进行实现。
首先将原有的工厂类 PhoneFactory 抽象出来,为抽象类或接口都行,视情况而定,这里将其抽象为接口。
public interface PhoneFactory {
Phone createPhone();
}
因为我们代理了小米和华为两个品牌,所以此处我们需要建造 2 个品牌代工厂,它们均实现 PhoneFactory 接口。
public class XiaomiFactory implements PhoneFactory {
@Override
public Phone createPhone() {
return new Xiaomi();
}
}
public class HuaweiFactory implements PhoneFactory {
@Override
public Phone createPhone() {
return new Huawei();
}
}
接下来使用的时候,直接在客户端创建具体的工厂对象生产手机即可,如下:
public class Client {
public static void main(String[] args) {
PhoneFactory factory = new HuaweiFactory();
Phone phone = factory.createPhone();
phone.call();
}
}
后期如果我们再代理多几个品牌的生产,只需要创建新的品牌工厂并实现 PhoneFactory 接口即可,原有代码不需要做任何改动便能完成多品牌代理生产的需求,遵循了简单工厂模式中没有做到的开闭原则,但也因此,工厂方法模式会增加比简单工厂模式更多新类。
3. UML 类图

4. 何时使用工厂方法模式?
在设计需要灵活的、可扩展的框架或者模块时,可以考虑使用工厂方法模式。在面向对象的世界里,万物皆对象,只要我们有创建对象的需求,并且这个对象是灵活多变时,使用工厂方法模式可以使代码的可读性、可维护性、可扩展性提升一个层次。
简单工厂模式和工厂方法模式如何选择?
我们知道,简单工厂模式其实就是工厂方法模式的弱化版,它适用于大部分比较简单的场景,如产品类型比较少,这种情况使用简单工厂模式是比较合理的。但如果我们需要创建的产品种类比较多且创建过程较为复杂,则选择工厂方法模式,将不同的产品隔离开来让它们各自变化,并且增加新的产品种类我们只需要扩展即可,不需要修改既有代码,更加灵活与安全。
5. 总结
优点:
- 保持了简单工厂模式的优点,并且克服了它的缺点,遵循了开闭原则。
缺点:
- 每增加一个产品类时需要同时增加一个新的工厂类,增加了工作量,在产品类型较多的情况下这个缺点更加突出。