php设计模式(三):工厂方法模式 (Factory Method)

2023-09-18 15:43:30 浏览数 (2)

工厂方法模式

工厂方法又称为:虚拟构造函数、Virtual Constructor、Factory Method。定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类中。

问题

接前一篇的 简单工厂 问题,简单工厂违背了开闭原则,每次修改或增添部件需要去工厂中修改工厂类,需要去修改工厂类的 Switch 具体逻辑。

也就是说我们每次修改都要去 简单工厂 的 Switch 增加或者删除,这即为不便,产品变多了,我们的工作也就越来越大了。

解决方法

工厂方法则将问题交给具体客户端(DIY组装电脑),需要什么部件实例化什么部件工厂类。让工厂的子类来确定实例化哪一个具体的产品类。

前面说到,产品变多,简单工厂 工作也就越来越大了,所以工厂方法模式对产品的每种类型新增一个工厂,以减少我们一个 简单工厂 的工作量,这样就将问题交给具体客户端。

结构

1个 interface 或者 abstract 产品基类

多个实现 interface 或者继承 abstract 的具体产品类

1个 interface 或者 abstract 工厂基类

多个实现 interface 或者继承 abstract 的具体工厂类

具体工厂类和具体产品类一一对应

在具体工厂类中实例化具体的产品类

代码示例

工厂类基类

部件工厂基类,制定创建产品方法。

代码语言:javascript复制
// Factory.php
interface Factory
{
    public function production();
}

PHP

Copy

具体工厂类

代码语言:javascript复制
// KeyboardFactory.php
class KeyboardFactory implements Factory
{
     public function production(): Product
    {
        return new KeyboardProduct();
    }
}

// MouseFactory.php
class MouseFactory implements Factory
{
    public function production(): Product
    {
        return new MouseProduct();
    }
}
...

PHP

Copy

产品类基类

代码语言:javascript复制
// Product.php
interface Product
{
    public function getPrice();
}

PHP

Copy

具体产品类

代码语言:javascript复制
// KeyboardProduct.php
class KeyboardProduct implements Product
{
    public function getPrice(): float
    {
        return 149.99;
    }
}

// MouseProduct.php
class MouseProduct implements Product
{
    public function getPrice(): float
    {
        return 49.99;
    }
}

PHP

Copy

组装的DIY台式电脑类

代码语言:javascript复制
// DiyComputer.php

// 键盘
$keyboardFactory = new KeyboardFactory();
$keyboard = $keyboardFactory->production();
$keyboardPrice = $keyboard->getPrice();
// 鼠标
$mouseFactory = new MouseFactory();
$mouse = $mouseFactory->production();
$mousePrice = $mouse->getPrice();
...
//总价格
echo $mousePrice   $keyboardPrice   ...;

PHP

Copy

UML

代码

工厂方法模式代码

优缺点

优点

  • 单一职责。将创建代码放在程序的单一位置,使得代码更容易维护。
  • 避免创建者和具体产品之间的紧密耦合。
  • 开闭原则。无需改变现有客户端代码(DIY组装电脑类),就能在程序中引入新的产品。

缺点

  • 引入许多新的子类,代码可能会因此变的更加复杂。

0 人点赞