[整理] 设计模式——工厂: 简单工厂、静态工厂、工厂方法、抽象工厂

要点

  • 所有的工厂都是用来封装对象的创建
  • 简单工厂, 虽然不是真正的设计模式,但仍不失为一个简单的方法,可以将客户端程序从具体类解耦
  • 工厂方法使用继承:把对象的创建委托给子类,子类实现工厂方法来创建对象。
  • 抽象工厂使用对象组合:对象的创建被实现在工厂接口所暴露出来的方法中。
  • 所有工厂模式都通过减少应用程序和具体类之间的依赖促进松耦合。
  • 工厂方法允许类将实例化延迟到子类进行。
  • 抽象工厂创建相关的对象家族,而不需要依赖它们的具体类。
  • 依赖倒置原则,指导我们避免依赖具体类型, 而要尽量依赖抽象。
  • 工厂是很有威力的技巧,帮助我们针对抽象编程,而不要针对具体类编程。

简单工厂

示例: 建立一个简单披萨工厂

class SimplePizzaFactory
{
    public createPizza(string $type): Pizza
    {
        $pizza = null;
        switch ($type) {
            case "cheese":
                $pizza = new CheesePizza();
                break;
                
            case "clam":
                $pizza = new ClamPizza();
                break;
                
            case "veggie":
                $pizza = new VeggiePizza();
                break;
                
            default:
                throw new Exception("不支持的披萨类型");
        }
        return $pizza;
    }
}

好处(以下的披萨指工厂生产的产品):

  • 客户端(指调用方)不必知道要创建的具体披萨类名
  • 披萨的创建从客户端代码中分离开,以后有实现变更时只需修改该类

静态工厂

利用静态方法定义一个“简单工厂”

好处:

  • 不需要实例化工厂即可创建所需对象

坏处:

  • 无法通过继承改变创建方法的行为

工厂方法 Factory Method

工厂方法模式: 通过让子类决定该创建的对象是什么, 来达到将对象创建的过程封装的目的.

正式定义: 工厂方法模式定义了一个创建对象的接口, 但由子类决定要实例化的类是哪一个. 工厂方法让类把实例化推迟到子类

参数化工厂方法: 根据传入的参数创建不同的对象.

工厂通常只生产一种对象, 不需要参数化.

↑ 工厂方法可能需要参数(也可能不需要)来指定所要的产品, 这两种形式都是有效的

abstract function factoryMethod(string $type): Product;
  • abstract 工厂方法是抽象的, 依赖子类来处理对象的创建
  • Product 工厂方法必须返回一个产品。 超类中定义的方法, 通常使用到工厂方法的返回值。
  • factoryMethod 工厂方法将客户(也就是超类中的代码)和实际创建具体产品的代码分隔开来


工厂方法的目的定义一个约定的方法,该方法用于创建一类对象,创建的具体对象由子类决定。

Eg.

  • 约定的创建方法 LoggerFactory::createLogger
  • 创建的一类对象 Logger
  • 具体的子类1 StdoutLoggerStdoutLoggerFactory 创建
  • 具体的子类2 FileLoggerFileLoggerFactory 创建

特点:

  • 具体对象的创建由各子类构建
  • 新增一种创建的对象时,必须配套一个专用的工厂(既是优点也是缺点)

简单工厂 的区别

简单工厂是将创建对象的过程延迟到工厂内部,但它有个问题:每次要新增创建的对象时必须去修改工厂类本身,这意味着这个工厂类很容易膨胀,同时这违反了开放封闭原则。

工厂方法则是将实例化的过程下沉到具体子工厂,需要新增创建的对象时,就新增一个对应的工厂。

UML 图

抽象工厂模式

定义: 抽象工厂模式提供一个接口(Interface), 用于创建具体或依赖对象的家族, 而不需要明确指定具体类.

抽象工厂允许客户使用抽象的接口来创建一组相关的产品, 而不需要知道(或关心)实际产出的具体产品是什么. 这样一来, 客户就从具体的产品中被解耦.

从抽象工厂中派生出具体工厂, 这些工厂生产相同的产品, 但是产品的实现不同.

抽象工厂与工厂方法?

抽象工厂的方法经常以工厂方法的方式实现.

  1. 抽象工厂的任务是定义一个创建一组产品的接口
  2. 这个接口内的每个方法都负责创建一个具体产品
  3. 利用实现抽象工厂的子类来提供这些具体产品的做法

所以, 在抽象工厂中利用工厂方法实现生产方法是相当自然的做法。

此处的"接口"是广义上的意思, 包含 interface/abstract class

工厂方法↓

抽象工厂↓

posted @ 2019-01-22 10:52  嘉兴Xing  阅读(699)  评论(0编辑  收藏  举报