【设计模式】工厂方法模式

1、定义

工厂方法 模式 是一种创建型的设计模式,其在父类中提供一个创建对象的方法,允许子类决定实例化对象的类型。其实就把产品对象的实际创建工作放到具体的子类工厂当中实现。

2、优缺点

  • 优点:
    • 可以避免创建者和具体产品之间的紧密耦合。
    • 单一职责原则。可以将产品创建代码放在程序的单一位置,从而使得代码更容易维护。
    • 开闭原则。无需更改现有客户端代码,就可以在程序中引入新的产品类型。
  • 缺点:
    • 每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,增加了系统的复杂度。

3、模式结构

  • 抽象工厂(Abstract Factory):提供一个创建产品的接口。调用者可以通过它访问具体工厂的工厂方法。
  • 具体工厂(Concrete Factory):继承自抽象工厂,并实现其创建对象的方法。
  • 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能。
  • 具体产品(Concrete Product):实现了抽象产品中所定义的接口,由具体工厂来创建,与同具体工厂之间是一一对应的。

4、具体代码

1、抽象工厂(Abstract Factory):提供一个创建产品的接口。调用者可以通过它访问具体工厂的工厂方法。

复制代码
<?php
/**
 * Created by PhpStorm
 * Author: fengzi
 * Date: 2024/2/22
 * Time: 17:55
 */

namespace app\admin\service\design_mode\factory_method;

/**
 * 抽象工厂类
 */
abstract class CarFactory
{
    abstract public function createCar(): Car;
}

2、具体工厂(Concrete Factory):继承自抽象工厂,并实现其创建对象的方法。

复制代码
<?php
/**
 * Created by PhpStorm
 * Author: fengzi
 * Date: 2024/2/22
 * Time: 17:55
 */

namespace app\admin\service\design_mode\factory_method;

/**
 * 宝马工厂
 *
 * 具体工厂类,继承自抽象工厂
 */
class BmwFactory extends CarFactory
{

    public function createCar(): Car
    {
        // TODO: Implement createCar() method.
        return new Bmw();
    }
}
复制代码
<?php
/**
 * Created by PhpStorm
 * Author: fengzi
 * Date: 2024/2/22
 * Time: 17:55
 */

namespace app\admin\service\design_mode\factory_method;

/**
 * 奔驰工厂
 *
 * 具体工厂类,继承自抽象工厂
 */
class BenzFactory extends CarFactory
{

    public function createCar(): Car
    {
        // TODO: Implement createCar() method.
        return new Benz();
    }
}

3、抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能。

复制代码
<?php
/**
 * Created by PhpStorm
 * Author: fengzi
 * Date: 2024/2/23
 * Time: 11:21
 */

namespace app\admin\service\design_mode\factory_method;

/**
 * 抽象产品类
 */
abstract class Car
{
    /**
     * 给汽车加油
     * 抽象方法,用于实现产品的功能
     * @return mixed
     * @Author: fengzi
     * @Date: 2024/2/23 11:26
     */
    public abstract function refuel();

    /**
     * 驾驶汽车
     * 抽象方法,用于实现产品的功能
     * @return mixed
     * @Author: fengzi
     * @Date: 2024/2/23 11:26
     */
    public abstract function drive();
}

4、具体产品(Concrete Product):实现了抽象产品中所定义的接口,由具体工厂来创建,与同具体工厂之间是一一对应的。

复制代码
<?php
/**
 * Created by PhpStorm
 * Author: fengzi
 * Date: 2024/2/23
 * Time: 11:22
 */

namespace app\admin\service\design_mode\factory_method;

/**
 * 具体产品类-宝马汽车
 */
class Bmw extends Car
{

    public function refuel()
    {
        // TODO: Implement refuel() method.
        echo  "给宝马车加油\n";
    }

    public function drive()
    {
        // TODO: Implement drive() method.
        echo  "驾驶宝马车\n";
    }
}
复制代码
<?php
/**
 * Created by PhpStorm
 * Author: fengzi
 * Date: 2024/2/23
 * Time: 11:22
 */

namespace app\admin\service\design_mode\factory_method;

/**
 * 具体产品类-奔驰汽车
 */
class Benz extends Car
{

    public function refuel()
    {
        // TODO: Implement refuel() method.
        echo "给奔驰车加油\n";
    }

    public function drive()
    {
        // TODO: Implement drive() method.
        echo "驾驶奔驰车\n";
    }
}

5、调用方式

复制代码
<?php
/**
 * 工厂方法模式
 * Author: fengzi
 * Date: 2024/2/22
 * Time: 17:16
 */

namespace app\admin\controller\design_mode;

use app\admin\service\design_mode\factory_method\BenzFactory;
use app\admin\service\design_mode\factory_method\BmwFactory;

class FactoryMethodController
{
    /**
     * 调用工厂方法模式
     * @return void
     * @Author: fengzi
     * @Date: 2024/2/26 9:56
     */
    public function index()
    {
        //调用奔驰方法
        $factory = new BenzFactory();
        $car = $factory->createCar();
        $car->refuel();
        $car->drive();

        //调用宝马方法
        $factory = new BmwFactory();
        $car = $factory->createCar();
        $car->refuel();
        $car->drive();
    }
}

6、调用结果展示:

5、工厂方法模式的精简版 - 简单工厂模式

简单工厂模式中的每个产品不用像工厂方法模式一样每个产品都对应一个工厂类,只需要通过一个工厂方法来判断性的创建对应产品。具体请看以下代码。

1、抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能。

复制代码
<?php
/**
 * Created by PhpStorm
 * Author: fengzi
 * Date: 2024/2/23
 * Time: 11:21
 */

namespace app\admin\service\design_mode\factory_method;

/**
 * 抽象产品类
 */
abstract class Car
{
    /**
     * 给汽车加油
     * 抽象方法,用于实现产品的功能
     * @return mixed
     * @Author: fengzi
     * @Date: 2024/2/23 11:26
     */
    public abstract function refuel();

    /**
     * 驾驶汽车
     * 抽象方法,用于实现产品的功能
     * @return mixed
     * @Author: fengzi
     * @Date: 2024/2/23 11:26
     */
    public abstract function drive();
}

2、具体产品(Concrete Product):实现了抽象产品中所定义的接口,由一个工厂方法来创建产品对象。

复制代码
<?php
/**
 * Created by PhpStorm
 * Author: fengzi
 * Date: 2024/2/23
 * Time: 11:22
 */

namespace app\admin\service\design_mode\factory_method;

/**
 * 具体产品类-奔驰汽车
 */
class Benz extends Car
{

    public function refuel()
    {
        // TODO: Implement refuel() method.
        echo "给奔驰车加油\n";
    }

    public function drive()
    {
        // TODO: Implement drive() method.
        echo "驾驶奔驰车\n";
    }
}
复制代码
<?php
/**
 * Created by PhpStorm
 * Author: fengzi
 * Date: 2024/2/23
 * Time: 11:22
 */

namespace app\admin\service\design_mode\factory_method;

/**
 * 具体产品类-宝马汽车
 */
class Bmw extends Car
{

    public function refuel()
    {
        // TODO: Implement refuel() method.
        echo  "给宝马车加油\n";
    }

    public function drive()
    {
        // TODO: Implement drive() method.
        echo  "驾驶宝马车\n";
    }
}

3、简单工厂的工厂类

复制代码
<?php
/**
 * Created by PhpStorm
 * Author: fengzi
 * Date: 2024/2/26
 * Time: 10:17
 */

namespace app\admin\service\design_mode\factory_method;

/**
 * 简单工厂类
 */
class SimpleFactory
{
    /**
     * 简单工厂模式
     * @param string $type  产品类型:benz奔驰,bmw宝马
     * @return string|void
     * @Author: fengzi
     * @Date: 2024/2/26 10:15
     */
    public function getProduct(string $type): Car
    {
        switch ($type)
        {
            case 'benz':
                return new Benz();
                break;
            case 'bmw':
                return new Bmw();
                break;
            default:
                return '';
        }
    }
}

4、调用方式

复制代码
<?php
/**
 * 简单工厂模式
 * Author: fengzi
 * Date: 2024/2/22
 * Time: 17:16
 */

namespace app\admin\controller\design_mode;

use app\admin\service\design_mode\factory_method\SimpleFactory;

class FactoryMethodController
{
    /**
     * 简单工厂模式
     * @Author: fengzi
     * @Date: 2024/2/26 10:15
     */
    public function simpleFactory()
    {
        $simpleFactory = new SimpleFactory();
        //调用奔驰方法
        $benz = $simpleFactory->getProduct('benz');
        $benz->refuel();
        $benz->drive();

        //调用宝马方法
        $bmw = $simpleFactory->getProduct('bmw');
        $bmw->refuel();
        $bmw->drive();
    }
}

5、调用结果展示

6、总结

  • 通常我们把被创建的对象称之为【产品】
  • 创建【产品】的对象称为【工厂】
  • 当产品比较固定且数量少的情况下,我们只需要一个工厂类就可以,这个模式下我们称之为【简单工厂】
相关推荐
JaguarJack8 小时前
FrankenPHP 原生支持 Windows 了
后端·php·服务端
BingoGo8 小时前
FrankenPHP 原生支持 Windows 了
后端·php
JaguarJack1 天前
PHP 的异步编程 该怎么选择
后端·php·服务端
BingoGo1 天前
PHP 的异步编程 该怎么选择
后端·php
JaguarJack2 天前
为什么 PHP 闭包要加 static?
后端·php·服务端
willow2 天前
Axios由浅入深
设计模式·axios
ServBay3 天前
垃圾堆里编码?真的不要怪 PHP 不行
后端·php
用户962377954483 天前
CTF 伪协议
php
七月丶4 天前
别再手动凑 PR 了:这个 AI Skill 会按仓库习惯自动建分支、拆提交、提 PR
人工智能·设计模式·程序员