PHP 设计模式系列 —— 简单工厂模式、工厂方法模式、抽象工厂模式

  • 简单工厂模式

简单工厂模式的定义:一个类可以根据不同的参数来获取不同的实例,一般这些被创建的实例都具有相同的父类。
静态工厂模式:一般的,我们将简单工厂模式中的用于创建不同实例的方法设置为静态方法,避免创建多个相同实例。
 

在简单工厂模式中用于被创建实例的方法通常为静态(static)方法,因此简单工厂模式又被成为静态工厂方法
 

示例代码

1、定义interface,手机有打电话和拍照的功能
InterfaceMobile.php

<?php

interface InterfaceMobile
{
    /**
     * 打电话
     * @return mixed
     */
    public function call();

    /**
     * 拍照
     * @return mixed
     */
    public function photograph();
}

MobileIPhone.php

<?php

/**
 * 苹果手机
 * Class MobileIPhone
 */
require_once __DIR__ . '/InterfaceMobile.php';

class MobileIPhone implements InterfaceMobile
{

    public function call()
    {
        // TODO: Implement call() method.
        echo "IPhone: call" . "<br/>";
    }

    public function photograph()
    {
        // TODO: Implement photograph() method.
        echo "IPhone: photograph" . "<br/>";
    }

}

MobileHuawei.php

<?php

/**
 * 华为手机
 * Class MobileIPhone
 */

require_once __DIR__ . '/InterfaceMobile.php';

class MobileHuawei implements InterfaceMobile
{

    public function call()
    {
        // TODO: Implement call() method.
        echo "Huawei: call" . "<br/>";
    }

    public function photograph()
    {
        // TODO: Implement photograph() method.
        echo "Huawei: photograph" . "<br/>";
    }

}

 MobileXiaomi.php

<?php

/**
 * 小米手机
 * Class MobileIPhone
 */
require_once __DIR__ . '/InterfaceMobile.php';

class MobileXiaomi implements InterfaceMobile
{

    public function call()
    {
        // TODO: Implement call() method.
        echo "Xiaomi: call" . "<br/>";
    }

    public function photograph()
    {
        // TODO: Implement photograph() method.
        echo "Xiaomi: photograph" . "<br/>";
    }

}

通过工厂类 Factory.php 去调用

<?php

/**
 * 工厂类
 * Class Factory
 */
class Factory
{
    private static $instance;

    public static function create($name)
    {
        $class = null;
        switch ($name) {
            case 'IPhone':
                require_once __DIR__ . '/MobileIPhone.php';
                self::$instance = new MobileIPhone();
                break;
            case 'Huawei':
                require_once __DIR__ . '/MobileHuawei.php';
                self::$instance = new MobileHuawei();
                break;
            case 'Xiaomi':
                require_once __DIR__ . '/MobileXiaomi.php';
                self::$instance = new MobileXiaomi();
                break;
            default:
                echo "类 {$name} 不存在";
                exit;
                break;
        }
        return self::$instance;
    }
}

实例化工厂类,生成不同的对象,不需要知道手机的实现细节

<?php

// 调用工厂

ini_set('display_errors', 1);
error_reporting(E_ALL);

require_once __DIR__ . '/Factoty.php';

$mobile_name = 'IPhone';

$instance = Factory::create($mobile_name);// 只需传入需要创建的手机类型即可,不需要知道细节: IPhone | Huawei | Xiaomi
$instance->call();
$instance->photograph();

简单工厂缺点:
系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,同样破坏了“开闭原则”;在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。 

  • 工厂方法模式

定义一个创建对象的接口,让子类决定哪个类实例化。 他可以解决简单工厂模式中的封闭开放原则问题。
 

代码示例:
沿用简单工厂模式中的 
InterfaceMobile.php
MobileIPhone.php
MobileHuawei.php
MobileXiaomi.php

 

新增接口类:
InterfaceFactory.php

<?php

/**
 * 工厂类
 * Class Factory
 */
interface InterfaceFactory
{
    public function create();
}

FactoryIPhone.php
 

<?php
require_once __DIR__ . '/InterfaceFactory.php';

class FactoryIPhone implements InterfaceFactory
{
    public function create()
    {
        // TODO: Implement create() method.
        echo "FactoryIPhone: create" . "<br/>";
        require_once __DIR__ . '/MobileIPhone.php';
        return new MobileIPhone();
    }
}

FactoryHuawei.php

<?php
require_once __DIR__ . '/InterfaceFactory.php';

class FactoryHuawei implements InterfaceFactory
{
    public function create()
    {
        // TODO: Implement create() method.
        echo "FactoryHuawei: create" . "<br/>";
        require_once __DIR__ . '/MobileHuawei.php';
        return new MobileHuawei();
    }
}

FactoryXiaomi.php

<?php
require_once __DIR__ . '/InterfaceFactory.php';

class FactoryXiaomi implements InterfaceFactory
{
    public function create()
    {
        // TODO: Implement create() method.
        echo "FactoryXiaomi: create" . "<br/>";
        require_once __DIR__ . '/MobileXiaomi.php';
        return new MobileXiaomi();
    }
}

调用

<?php

// 调用工厂


ini_set('display_errors', 1);
error_reporting(E_ALL);

require_once __DIR__ . '/FactoryIPhone.php';
require_once __DIR__ . '/FactoryHuawei.php';
require_once __DIR__ . '/FactoryXiaomi.php';

$mobile_name = 'IPhone';

if ($mobile_name == 'IPhone') {
    // 苹果手机
    $factory = new FactoryIPhone();
} elseif ($mobile_name == 'Huawei') {
    // 华为手机
    $factory = new FactoryHuawei();
} elseif ($mobile_name == 'Huawei') {
    // 小米手机
    $factory = new FactoryXiaomi();
}

$instance = $factory->create();
$instance->call();
$instance->photograph();

 

  • 抽象工厂模式

抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂

<?php

/**
* 抽象工厂方法
* 提供一个创建一系列相关或相互依赖对象的接口。
* 注意:这里和工厂方法的区别是:一系列,而工厂方法则是一个。
* 那么,我们是否就可以想到在接口create里再增加创建“一系列”对象的方法呢?
*/

interface PeopleInterface
{
    // 走路
    function walk();
}

class ManStrong implements PeopleInterface
{
    function walk()
    {
        // TODO: Implement Walk() method.
        echo 'ManStrong: walk';
    }
}

class ManThin implements PeopleInterface
{
    function walk()
    {
        // TODO: Implement Walk() method.
        echo 'Man: walk';
    }
}

class WomenStrong implements PeopleInterface
{
    function walk()
    {
        // TODO: Implement walk() method.
        echo "WomenStrong: walk";
    }
}

class WomenThin implements PeopleInterface
{
    function walk()
    {
        // TODO: Implement walk() method.
        echo "WomenThin: walk";
    }
}

// 将对象的创建抽象成一个接口。
interface AbstractFactory
{
    function createStrong();
    function createThin();
}


class FactoryMan implements AbstractFactory
{
    function createStrong()
    {
        return new ManStrong();
    }

    function createThin()
    {
        return new ManThin();
    }
}

class FactoryWoman implements AbstractFactory
{
    function createStrong()
    {
        return new WomenStrong();
    }

    function createThin()
    {
        return new WomenThin();
    }
}

$factory = new FactoryMan();
$man = $factory->createStrong();
$man->walk();

区别:

简单工厂模式:用来生产同一等级结构中的任意产品。对与增加新的产品,无能为力

工厂模式 :用来生产同一等级结构中的固定产品。(支持增加任意产品)   

抽象工厂 :用来生产不同产品族的全部产品。(对于增加新的产品,无能为力;支持增加产品族)  

以上三种工厂 方法在等级结构和产品族这两个方向上的支持程度不同。所以要根据情况考虑应该使用哪种方法

适用范围:

简单工厂模式:

工厂类负责创建的对象较少,客户只知道传入工厂类的参数,对于如何创建对象不关心。

工厂方法模式:

当一个类不知道它所必须创建对象的类或一个类希望由子类来指定它所创建的对象时,当类将创建对象的职责委托给多个帮助子类中得某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候,可以使用工厂方法模式。

抽象工厂模式:

一个系统不应当依赖于产品类实例何如被创建,组合和表达的细节,这对于所有形态的工厂模式都是重要的。这个系统有多于一个的产品族,而系统只消费其 中某一产品族。同属于同一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来。系统提供一个产品类的库,所有的产品以同样的接口出现,从 而使客户端不依赖于实现。

无论是简单工厂模式、工厂模式还是抽象工厂模式,它们本质上都是将不变的部分提取出来,将可变的部分留作接口,以达到最大程度上的复用。究竟用哪种设计模式更适合,这要根据具体的业务需求来决定。

-

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值