工厂模式三姐妹之简单工厂模式

简单工厂模式。

枯燥的定义: 在一个类的方法中实例化其它的类,这个类就叫做工厂类,对应的方法叫做工厂方法

简单的例子:

<?php
function factory(){
    return new Product();
}

我们先看以下用简单工厂模式实现的计算器代码(改代码只做演示):

<?php
//计算基类
interface CalculateContract
{
    public function calculate(...$param);
}
//加法实现子类
class Add implements CalculateContract{
    public function calculate(...$param)
    {
        return array_sum($param);
    }
}
//减法实现子类
class Subtraction implements CalculateContract
{
    public function calculate(...$param)
    {
        if (count($param) < 2) {
            throw new InvalidArgumentException();
        }
        $minuend = array_shift($param);
        foreach ($param as $subtrahend) {
            $minuend -= $subtrahend;
        }
        return $minuend;
    }
}
//计算工厂类
class CalculateFactory{
    //工厂方法
    public static function getCalculate($ope){
        switch($ope){
            case '+':
                return new Add();
            case '-':
                return new Subtraction();
            default:
                throw new Exception('has not this invoke!');
        }
    }
}

//逻辑代码
$calculateMethod = CalculateFactory::getCalculate('+');
echo $calculateMethod->calculate(1,2,3);

我们来看看简单工厂的 UML 图:

简单工厂的优点:

  • 使用工厂类可以将客户端和具体的产品解耦,利于后期的维护和修改。


简单工厂的不足:

  • 正如你想到的,如果你需要添加添加新的运算方式,你不仅需要加新的类,还需要改变工厂类,增加对应新类生成代码,这样就违背了面向对象的一个原则: 开放-封闭原则

再来一个形象例子。

现有这样一个场景,系统登陆时候需要通过手机给用户发送验证码。

  • 不好的一种写法。
<?php

class AliSms{
    public function sendVerifyCode(){
        //发送逻辑
    }
}

class SmsServer
{
    protected $smsHandler;
    
    public function __construct()
    {
        $this->smsHandler = new AliSms();
    }
    
    public function sendVerifyCode()
    {
        $this->smsHandler->sendVerifyCode();
    }
}

上面写法缺点是很明显的,SmsServerAliSms 耦合到了一起,这样,如果以后你想换其它的短信服务商,那么你就必须修改 SmsServer 类。

  • 通过简单工厂模式改进后。
<?php
//Sms 抽象
interface SmsContract
{
    public function sendVerifyCode();
}

//具体的 Sms 实现,通过抽象来限制具体实现必须具有 sendVerifyCode 功能
class AliSms implements SmsContract
{
    public function sendVerifyCode()
    {
        //发送逻辑
    }
}

// Sms 工厂,作用是将具体的 Sms 和 SmsServer 解耦
class SmsFactory
{
    static public function getSmsHandler()
    {
        return new AliSms();
    }
}

// Sms 服务类
class SmsServer
{
    protected $smsHandler;
    
    public function __construct()
    {
        $this->smsHandler = SmsFactory::getSmsHandler();
    }
    
    public function sendVerifyCode()
    {
        $this->smsHandler->sendVerifyCode();
    }
}

通过简单工厂模式改进后,通过 SmsFactory 工厂将 SmsServer 和具体的 Sms 类解耦,这样无论以后需要将短信服务商换成哪一家,只需修改工厂类中的工厂方法。

Snail's Blog
请先登录后发表评论
  • 最新评论
  • 总共0条评论
  • 本博客使用免费开源的 laravel-bjyblog v5.5.1.3 -develop 搭建 © 2014-2018 www.snail-c.cn 版权所有 ICP证:蜀ICP备18023253号-1
  • 联系邮箱:459921737@qq.com