【重温23种设计模式】之工厂方法模式

来源:mikechen的互联网架构

工厂方法模式 简单工厂模式 的进一步抽象和升级,使用频次也更高。

工厂方法模式实现了可扩展,同时满足开闭原则,解决了简单工厂模式每次添加新的产品时,都需要修改工厂类的问题。

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

大家好,我是mikechen。本文是《深入浅出设计模式》的第 10 篇。刚结束的设计模式系列篇:七大设计原则(2万+字、40多张图解),大家反响还不错。

为方便学习,我已将全部内容更新到《深入浅出设计模式》PDF 了,该PDF目前有 2+万字,50+张图解,80多页,内容涵盖设计模式的 7 大原则、23 种设计模式。图文并茂非常详细,夯实基础、复习备面都用得上,需要的同学文末自取。

01
  工厂方法模式的定义

工厂方法模( Factory method pattern),又称为工厂模式。

工厂方法模式定义工厂父类负责定义创建对象的公共接口,而子类则负责生成具体的对象。

工厂方法模式的特点是:构建的都是同一类型的对象(实现相同的接口);且每一类对象对应一个工厂。

02
  工厂方法模式的结构

工厂方法模式的 UML类图

工厂方法模式的 4 个重要角色包括象工厂、具体工厂、抽象产品、具体产品。

  • Product:抽象产品类。

  • ConcreteProduct:具体产品类,实现Product接口。

  • Factory:抽象工厂类,该方法返回一个Product类型的对象。

  • ConcreteFactory:具体工厂类,返回ConcreteProduct实例。


03
  工厂方法模式解决问题

工厂方法模式简单工厂模式的进一步抽象和升级,它解决了简单工厂模式每当添加新的产品品类的时候,都需要修改工厂类的问题。

在没有引入工厂方法模式前,我们每次需要增加一种产品,就需要去修改工厂类的方法逻辑,这就违背了开闭原则,不易形成高内聚、松耦合的结构,维护非常麻烦。

工厂方法模式可以在不修改原来代码的情况下,让系统引进新的产品,即满足开闭原则。

04
  工厂方法模式的实现

这里我们依然沿用《秒懂简单工厂模式》中手机产品的例子。

源码示例:

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{    @Override    public void start() {        System.out.println("华为手机启动");    }}


小米手机:









package com.mikechen.java.design.factory.simple;
public class XiaoMiPhone extends Phone{    @Override    public void start() {        System.out.println("小米手机启动");    }}


苹果手机:









package com.mikechen.java.design.factory.simple;
public class IPhone extends Phone{    @Override    public void start() {        System.out.println("苹果手机启动");    }}

3)创建抽象工厂

其中,有一个 createPhone 方法,我们想要生产哪个品牌的手机,就生产哪个:






package com.mikechen.java.design.factory.simple;
public abstract class PhoneFactory {    public abstract T createPhone(Class clz);}

4)具体工厂

假设位于深圳的华强北是一个具体的工厂,它继承抽象工厂,通过反射来生产不同厂家的手机:





















package com.mikechen.java.design.factory.simple;
/** * 深圳华强北工厂 */public class HQBPhoneFactor extends PhoneFactory {    @Override    public T 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图就更加容易理解了:

05
  工厂方法模式的优缺点

优点:

  • 灵活性增强:对于新产品的创建,只需多写一个相应的工厂类。

  • 典型的解耦框架:高层模块只需要知道产品的抽象类,无须关心其他实现类。


点:

  • 系统的复杂度增加添加新产品时,需要增加新产品类,同时提供与之对应的具体工厂类,系统类的个数将成对增加。

  • 一个具体工厂只能创建一种具体产品,如果要更换另外一种产品,仍然需要修改实例化的具体工厂类。


06
  工厂方法模式的应用场景

  • 当一个类不知道它所需要的对象的类时; 

  • 当一个类希望通过其子类来指定创建对象时。 


07
  与简单工厂模式的区别

厂方法模式与简单工厂模式的区别

  • 工厂方法模式:客户端不知道它所需要的对象的类,抽象工厂类通过其子类来指定创建哪个对象,不违背开闭原则。

  • 简单工厂模式:在工厂类中包含了必要的逻辑判断,根据不同的条件、来动态实例化相关的类,违背了开闭原则。


仍以生产手机为例,假设我们需要生产苹果手机。

  • 工厂方法模式:只需要直接创建产品,不需要去修改工厂类。

  • 简单工厂模式:需要在工厂类中再添加一个 Case 分支条件,这违背了开闭原则,因为对修改也开放了。

开闭原则还不太理解的同学,看这篇设计模式七大原则最全总结 


总结


通过本文,我们了解并掌握了工厂方法模式的所有核心知识,包括工厂方法模式的概念、原理、应用场景、实现等

工厂方法模式体现了面向接口编程的思路,它并不是简单把 New 的过程换成了函数,而是抽象出一套面向接口的设计模式。

工厂方法模式在保留简单工厂模式的封装优点的同时,让扩展变得更加简单,让继承变得可行,增加了多态性的体现。


请使用浏览器的分享功能分享到微信等