PHP设计模式之工厂方法模式

PHP设计模式之工厂方法模式

上回说到,简单工厂不属于GoF的二十三种设计模式,这回可就来真家伙了,大名顶顶的工厂方法模式前来报道!php

GoF类图解释

工厂方法模式对比简单工厂来讲,最核心的一点,其实就是将实现推迟到子类。怎么理解呢?咱们能够将上回的简单工厂当作父类,而后有一堆子类去继承它。createProduct()这个方法在父类中也变成一个抽象方法。而后全部的子类去实现这个方法,再也不须要用switch去判断,子类直接返回一个实例化的对象便可。git

GoF定义:定义一个用于建立对象的接口,让子类决定实例化哪个类。Factory Method使一个类的实例化推迟到其子类。github

GoF类图设计模式

工厂方法结构类图

  • 类图中的Product为产品
  • 类图中的Creator为建立者
  • 建立者父类有一个抽象的FactoryMethod()工厂方法
  • 全部建立者子类须要实现这个工厂方法,返回对应的具体产品
  • 建立者父类能够有一个AnOperation()操做方法,直接返回product,能够使用FactoryMethod()去返回,这样外部只须要统一调用AnOperation()

代码实现this

首先是商品相关的接口和实现类,和简单工厂的相似:阿里云

// 商品接口
interface Product{
    function show() : void;
}

// 商品实现类A
class ConcreteProductA implements Product{
    public function show() : void{
        echo "I'm A.\n";
    }
}
复制代码

接下来是建立者的抽象和实现类:spa

// 建立者抽象类
abstract class Creator{

    // 抽象工厂方法
    abstract protected function FactoryMethod() : Product;

    // 操做方法
    public function AnOperation() : Product{
        return $this->FactoryMethod();
    }
}

// 建立者实现类A
class ConcreteCreatorA extends Creator{
    // 实现操做方法
    protected function FactoryMethod() : Product{
        return new ConcreteProductA();
    }
}
复制代码

这里和简单工厂就有了本质的区别,咱们去掉了恶心的switch,让每一个具体的实现类来进行商品对象的建立。没错,单一和封闭,每一个单独的建立者子类只在工厂方法中和一个商品有耦合,有没有其余商品和其余的工厂来跟客户合做过这个子类彻底不知道。设计

一样仍是拿手机来比喻:我是一个卖手机的批发商(客户Client,业务方),我须要一批手机(产品ProductA),因而我去让富X康(工厂Creator)来帮我生产。我跟富士康说明了需求,富士康说好的,让个人衡阳工厂(ConcreteCreatorA)来搞定,不须要总厂上,你这小单子,洒洒水啦。而后过了一阵我又须要另外一种型号的手机(产品ProductB),富士康看了看后又让郑州富士康(ConcreteCreatorB)来帮我生产。反正无论怎么样,他们老是给了我对应的手机。并且郑州工厂并不知道衡阳工厂生产过什么或者有没有跟我合做过,这一切只有我和总工厂知道。code

完整代码:工厂方法模式cdn

实例

场景:光说不练假把式,把上回的短信发送改造改造,咱们依然仍是使用上回的那几个短信发送商。毕竟你们已经很熟悉了嘛,不过之后要更换也说不定,商场如战场,你们仍是利益为先。这样的话,咱们经过工厂方法模式来进行解耦,就能够方便的添加修改短信提供商咯。

短信发送类图

短信发送工厂方法

代码实现

<?php

interface Message {
    public function send(string $msg);
}

class AliYunMessage implements Message{
    public function send(string $msg){
        // 调用接口,发送短信
        // xxxxx
        return '阿里云短信(原阿里大鱼)发送成功!短信内容:' . $msg;
    }
}

class BaiduYunMessage implements Message{
    public function send(string $msg){
        // 调用接口,发送短信
        // xxxxx
        return '百度SMS短信发送成功!短信内容:' . $msg;
    }
}

class JiguangMessage implements Message{
    public function send(string $msg){
        // 调用接口,发送短信
        // xxxxx
        return '极光短信发送成功!短信内容:' . $msg;
    }
}


abstract class MessageFactory{
    abstract protected function factoryMethod();
    public function getMessage(){
        return $this->factoryMethod();
    }
}

class AliYunFactory extends MessageFactory{
    protected function factoryMethod(){
        return new AliYunMessage();
    }
}

class BaiduYunFactory extends MessageFactory{
    protected function factoryMethod(){
        return new BaiduYunMessage();
    }
}

class JiguangFactory extends MessageFactory{
    protected function factoryMethod(){
        return new JiguangMessage();
    }
}

// 当前业务须要使用百度云
$factory = new BaiduYunFactory();
$message = $factory->getMessage();
echo $message->send('您有新的短消息,请查收');
复制代码

完整源码:短信发送工厂方法

说明

  • 和类图彻底一致,基本不须要什么说明了吧,注意工厂方法模式的特色,实现推迟到了子类!!
  • 业务调用的时候须要耦合一个Factory子类。确实是这样,若是你想一个统一的出口来调用,请在外面加一层简单工厂就好啦,这就当成一道思考题吧
  • 不拘泥于目前的形式,能够不用抽象类,直接用一个接口来定义工厂方法,摒弃掉getMessage()方法,外部直接调用公开的模板方法(factoryMethod)便可

下期看点

抽象工厂模式,老大哥即将登场。压轴的老是最强悍的,让咱们看看老大哥的本事!

相关文章
相关标签/搜索