陈大剩博客

php设计模式(二):简单工厂模式 (Simple Factory)

  • 陈大剩
  • 2022-11-17 23:47:13
  • 862

简单工厂模式

简单工厂模式又称为静态工厂方法模型,它属于类创建型模式,简单工厂并不属于23种设计模式,刚开始学习设计模式的同学,对简单工厂模式、工厂方法、抽象工厂中的工厂一知半解,其实白话点来说:这些模式一定会有一个工厂类,子类并不需要知道工厂细节,只需新建工厂创建产品即好。

简单工厂模式的优点在于将对象的 创建使用 分离,客户端只需要知道所需产品的名称或者类型,而不需要知道产品的具体实现细节。这样可以降低客户端的耦合度,同时也便于扩展和修改产品的实现。

问题

假设你正在开发一款组装DIY台式电脑的应用,最初版本只需要拼装一台台式电脑并计算出每台总部件价格即可,因此大部分代码都在DIY台式电脑的类中。

// DiyComputer.php
// 鼠标
$mouse = new Mouse();
$mousePrice = $mouse->getPrice();
// 键盘
$keyboard = new Keyboard();
$keyboardPrice = $keyboard->getPrice();
// 显示器
$display = new Display();
$displayPrice = $display->getPrice();

....
// 计算组装所有部件价格
echo $mousePrice + $keyboardPrice + $displayPrice + ...;

过了一段时间,使用DIY台式电脑的用户都觉得普通有线键盘不好用,需要换成无线键盘,这时你可能需要对每个DIY台式电脑的类修改键盘类代码。

// DiyComputer.php
// 鼠标
$mouse = new Mouse();
$mousePrice = $mouse->getPrice();
// 键盘
// $keyboard = new Keyboard();
$keyboard = new WirelessKeyboard();
$keyboardPrice = $keyboard->getPrice();
// 显示器
$display = new Display();
$displayPrice = $display->getPrice();

....
// 计算组装所有部件价格
echo $mousePrice + $keyboardPrice + $displayPrice + ...;

糟糕的是,如果以后这些DIY台式电脑的用户需要换其它部件,很有可能需要再次对这些代码进行大幅度修改。

解决方案

简单工厂方法模式解决频繁更换各个部件,无法预知对象确切类别及其依赖关系时,可以用简单工厂方法。

白话文:需求频繁变动,没有切确的功能,避免代码多次重复改,可以采用此方法。

不需要客户端中去实例化某个类,客户端只需要穿一个产品名字给 简单工厂就行,简单工厂用 Switch 判断返回。

就如果老板让你做一件事,他不管你怎么做,只要结果,你负责过程,具体你去哪个部门借什么工具完成,老板不管你,那么这样老板是不是少了很多事呢?(减少了耦合),当然你的工作就变多了(谁叫你是打工人)。

STEP 1 建立产品类

建立一个产品基类。如 Product 产品基类。然后,确保所有部件实现产品基接口。例如,鼠标实现 产品 接口;所有部件都实现 键盘 接口,以此类推。

STEP 2 建立工厂

建立一个组装工厂,其中有 production 生产产品类方法,production 方法通过传入的值, Switch 选择创建对象。客户端知道工厂提供 所有的部件创建方法,但是并不关心其具体实现方式

结构

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

代码示例

DIY台式电脑部件工厂类

//Factory.php

class Factory
{
    /**
     * 生产工厂
     * @param string $product
     * @return Product
     */
    static public function production(string $product): Product
    {
        switch ($product) {
            case 'mouse':
                $result = new Mouse();
                break;
            case 'keyboard':
                $result = new Keyboard();
                break;
            case 'display':
                $result = new Display();
                break;
            default:
                throw new \InvalidArgumentException('没有此部件');
        }
        return $result;
    }
}

部件产品接口基类

// Product.php

interface Product
{
    public function getPrice();
}

具体部件产品类

// Mouse.php

class Mouse implements Product
{
    public function getPrice(): float
    {
        return 499.99;
    }
}

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

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

组装的DIY台式电脑类

DiyComputer.php

// 生成鼠标
$mouse = Factory::production('mouse');
$mousePrice = $mouse->getPrice();
// 生成键盘
$keyboard = Factory::production('keyboard');
$keyboardPrice = $keyboard->getPrice();
// 生成显示器
$display = Factory::production('display');
$displayPrice = $display->getPrice();
....
// 计算组装所有部件价格
echo $mousePrice + $keyboardPrice + $displayPrice + ...;

uml

简单工厂模式

优缺点

优点

  • 可以避免具体产品和创建者之间紧密耦合。

缺点

  • 工厂需要引入很多新的子类,代码可能会因此变得更复杂。
  • 违背了开闭原则,添加新的部件必须去工厂类中修改循环语句
分享到:
0

说点儿什么吧

头像

表情

本站由陈大剩博客程序搭建 | 湘ICP备2023000975号| Copyright © 2017 - 陈大剩博客 | 本站采用创作共用版权:CC BY-NC 4.0

站长统计| 文章总数[115]| 评论总数[9]| 登录用户[22]| 时间点[118]

logo

登入

社交账号登录