来源:mikechen的互联网架构
工厂方法模式是 简单工厂模式 的进一步抽象和升级,使用频次也更高。
工厂方法模式实现了可扩展,同时满足开闭原则,解决了简单工厂模式每次添加新的产品时,都需要修改工厂类的问题。

今天,我们主要了解工厂方法模式。

大家好,我是mikechen。本文是《深入浅出设计模式》的第 10 篇。刚结束的设计模式系列篇:七大设计原则(2万+字、40多张图解),大家反响还不错。
为方便学习,我已将全部内容更新到《深入浅出设计模式》PDF 了,该PDF目前有 2+万字,50+张图解,80多页,内容涵盖设计模式的 7 大原则、23 种设计模式。图文并茂非常详细,夯实基础、复习备面都用得上,需要的同学文末自取。

工厂方法模式( Factory method pattern),又称为工厂模式。
工厂方法模式定义工厂父类负责定义创建对象的公共接口,而子类则负责生成具体的对象。
工厂方法模式的特点是:构建的都是同一类型的对象(实现相同的接口);且每一类对象对应一个工厂。
工厂方法模式的 UML类图
工厂方法模式的 4 个重要角色包括抽象工厂、具体工厂、抽象产品、具体产品。

Product:抽象产品类。
ConcreteProduct:具体产品类,实现Product接口。
Factory:抽象工厂类,该方法返回一个Product类型的对象。
ConcreteFactory:具体工厂类,返回ConcreteProduct实例。
工厂方法模式是简单工厂模式的进一步抽象和升级,它解决了简单工厂模式每当添加新的产品品类的时候,都需要修改工厂类的问题。
在没有引入工厂方法模式前,我们每次需要增加一种产品,就需要去修改工厂类的方法逻辑,这就违背了开闭原则,不易形成高内聚、松耦合的结构,维护非常麻烦。
工厂方法模式可以在不修改原来代码的情况下,让系统引进新的产品,即满足开闭原则。
这里我们依然沿用《秒懂简单工厂模式》中手机产品的例子。
源码示例:
1)创建抽象产品
手机的产品类,有一个 start 方法用于手机启动:
package com.mikechen.java.design.factory.simple;public abstract class Phone{public abstract void start();}
2)创建具体产品
具体的电脑产品分别是华为、小米和苹果手机.
华为手机:
package com.mikechen.java.design.factory.simple;public class HuaWeiPhone extends Phone{@Overridepublic void start() {System.out.println("华为手机启动");}}
小米手机:
package com.mikechen.java.design.factory.simple;public class XiaoMiPhone extends Phone{@Overridepublic void start() {System.out.println("小米手机启动");}}
苹果手机:
package com.mikechen.java.design.factory.simple;public class IPhone extends Phone{@Overridepublic void start() {System.out.println("苹果手机启动");}}
3)创建抽象工厂
其中,有一个 createPhone 方法,我们想要生产哪个品牌的手机,就生产哪个:
package com.mikechen.java.design.factory.simple;public abstract class PhoneFactory {public abstractT createPhone(Class clz); }
4)具体工厂
假设位于深圳的华强北是一个具体的工厂,它继承抽象工厂,通过反射来生产不同厂家的手机:
package com.mikechen.java.design.factory.simple;/*** 深圳华强北工厂*/public class HQBPhoneFactor extends PhoneFactory {@OverridepublicT createPhone(Class clz) { Phone phone=null;String classname=clz.getName();try {//通过反射来生产不同厂家的电脑Phone= (Phone) Class.forName(classname).newInstance();} catch (Exception e) {e.printStackTrace();}return (T) Phone;}}
客户端调用
package com.mikechen.java.design.factory.simple;public class Client {public static void main(String[]args) {PhoneFactory phoneFactory = new HQBPhoneFactor();HuaWeiPhone mHuaWeiPhone=phoneFactory.createphone(HuaWeiPhone.class);mHuaWeiPhone.start();XiaoMiHuaWeiPhone mXiaoMiHuaWeiPhone=PhoneFactory.createPhone(XiaoMiHuaWeiPhone.class);mXiaoMiHuaWeiPhone.start();IphoneComputer mIPhone=PhoneFactory.createphone(Iphone.class);mIphone.start();}}
结构很简单,看看下面的UML图就更加容易理解了:

优点:
灵活性增强:对于新产品的创建,只需多写一个相应的工厂类。
典型的解耦框架:高层模块只需要知道产品的抽象类,无须关心其他实现类。
缺点:
系统的复杂度增加:添加新产品时,需要增加新产品类,同时提供与之对应的具体工厂类,系统类的个数将成对增加。
一个具体工厂只能创建一种具体产品,如果要更换另外一种产品,仍然需要修改实例化的具体工厂类。
当一个类不知道它所需要的对象的类时;
当一个类希望通过其子类来指定创建对象时。
工厂方法模式与简单工厂模式的区别:
工厂方法模式:客户端不知道它所需要的对象的类,抽象工厂类通过其子类来指定创建哪个对象,不违背开闭原则。
简单工厂模式:在工厂类中包含了必要的逻辑判断,根据不同的条件、来动态实例化相关的类,违背了开闭原则。
仍以生产手机为例,假设我们需要生产苹果手机。
工厂方法模式:只需要直接创建产品,不需要去修改工厂类。
简单工厂模式:需要在工厂类中再添加一个 Case 分支条件,这违背了开闭原则,因为对修改也开放了。
对开闭原则还不太理解的同学,看这篇:设计模式七大原则最全总结 。
通过本文,我们了解并掌握了工厂方法模式的所有核心知识,包括工厂方法模式的概念、原理、应用场景、实现等。
工厂方法模式体现了面向接口编程的思路,它并不是简单把 New 的过程换成了函数,而是抽象出一套面向接口的设计模式。
工厂方法模式在保留简单工厂模式的封装优点的同时,让扩展变得更加简单,让继承变得可行,增加了多态性的体现。
