在本文中,对于属于同一产品族的产品,我们认为它是同一类产品。比如鼠标有惠普、戴尔两个品牌,但我们认为它属于同一类产品。
另外,鼠标和键盘是不同类的产品。
简单工厂模式又叫做静态工厂方法模式(static Factory Method pattern),它通过使用静态方法接收不同的参数来返回不同的实例对象。
简单工厂模式不是 23 种里的一种,它只有一个工厂,只生产一类产品,通过静态方法来创建产品实例对象。
比如下图中的鼠标工厂,专业生产鼠标。通过静态方法 createMouse() 来生产鼠标。给参数 0,生产戴尔鼠标,给参数 1,生产惠普鼠标。
组成角色:
优点:简单工厂可以根据需要创建出对应的产品,而不需要知道产品具体对应的是哪个类。实现客户端和产品类代码分离。
缺点:违背开闭原则,如果需要新增其他产品类,就必须在工厂类中新增 if-else 逻辑判断。所以它不在 23 种设计模式中。
适用场景:简单工厂模式适用于业务简单,产品固定不会经常改变工厂类的情况。
为了便于理解,我们将这种工厂模式称为普通工厂模式吧!
在普通工厂模式中,工厂可以有多个,但生产的产品还是只能有一类(比如这里的鼠标)。
该模式在简单工厂模式的基础上,多了一个抽象的鼠标工厂(抽象类或接口),再由具体的鼠标工厂去继承/实现它。此时生产哪种鼠标不再由参数决定,而是看你创建的是哪个具体的鼠标工厂。
后续直接调用鼠标工厂.生产鼠标()即可。
组成角色:
优点:完全实现开闭原则,实现了可扩展和更复杂的层次结构。明确了职责,具有多态性。
缺点:如果业务增加,会使得系统中类的个数成倍增加,提高了代码的复杂度。
抽象工厂模式可以有多个工厂、且每个工厂可以生产多类产品。
比如 PC 工厂即支持生产鼠标,又支持生产键盘。
戴尔工厂和惠普工厂继承它后可以分别生产戴尔鼠标 + 戴尔键盘,和惠普鼠标 + 惠普键盘。
若创建具体工厂时选择了戴尔工厂。则后续工厂.生产鼠标()会生产戴尔鼠标,工厂.生产键盘()会生产戴尔键盘。
组成角色:
在抽象工厂模式中,假设我们需要增加一个工厂
假设我们增加华硕工厂,则我们需要增加华硕工厂,和戴尔工厂一样,继承 PC 厂商。
之后创建华硕鼠标,继承鼠标类。创建华硕键盘,继承键盘类即可。
在抽象工厂模式中,假设我们需要增加一个产品
假设我们增加耳麦这个产品,则首先我们需要增加耳麦这个父类,再加上戴尔耳麦,惠普耳麦这两个子类。
之后在 PC 厂商这个父类中,增加生产耳麦的接口。最后在戴尔工厂,惠普工厂这两个类中,分别实现生产戴尔耳麦,惠普耳麦的功能。 以上。
优点:在一个工厂中,能创建多类产品。相比工厂模式,这大大减少了工厂类的数量。
缺点:因为在一个工厂中能创建多类产品,导致需要对产品类型进行拓展时,影响范围较大。比如上面的例子中,增加了一个耳麦产品,就需要同时修改 HpFactory、DellFactory 和 PcFactory。
对于什么是工厂方法模式,有两种不同的观点:
工厂模式提供了一种创建对象的方式,而无需指定要创建的具体类,这使得创建对象的过程与使用对象的过程实现了分离。
一句话概括工厂模式
生活中的工厂模式
简单工厂模式、普通工厂模式、抽象工厂模式的关联:简单工厂模式适用于业务简单,产品固定不会经常改变工厂类的情况,但不满足开闭原则,可拓展性不好。为此,可以使用普通工厂模式来提高拓展性。但在业务过于复杂的情况下,普通工厂模式又会使得系统中类的个数成倍增加,这提高了代码的复杂度。此时,为了减少普通工厂模式中的子类和工厂类数量过多问题,可以考虑使用抽象工厂模式。综上,没有哪种方法是万金油,要针对业务场景来使用哪种工厂模式。