全网最详细的PHP设计模式系列(三)简单工厂模式(Simple Factory)

教程帖子 2019年12月23日 阅读 138 豆浆大叔

前言

学而不思则罔 思而不学则殆,每一个人的

回顾 小插曲

至于为什么写PHP的设计模式?说实话,有一些小伙伴(刚刚初出茅庐/已经两三年经验)去面试被问到PHP设计模式,支支吾吾说不上来。也不能说是不想说,只是概念模模糊糊,可能以前看过,但是又不使用,那就忘记了。而有的记住但是写不出来,也很尴尬,毕竟两三年经验的人还是需要面试,笔试。

  • 概念模糊
  • 不知道怎么去使用设计模式,什么场景下
  • 动手能力差
  • 只会增删改查

上面是我总结的四点,举个例子,ThinkPHP5.6+,增加了门面模式,估计没在意的同学可能没有仔细追究,框架为什么使用这个模式,有什么好处?说到底只会使用,可能离开框架什么都不会了!

PHP超简单理解的单例模式

废话到这里结束,下面开始正题走起。

什么叫简单工厂设计模式,它能做什么?

  • 什么是简单工厂模式

简单工厂模式又叫静态工厂方法模式,主要作用是通过一个简单工厂类来实例化(创建)各个类的对象,而不需要通过new来实例化对象。优点在于,工厂类中包含了一定的逻辑判断,会根据客户端的选择条件动态实例化相关的类。缺点在于,当需要增加新的功能类时,需要去修改工厂类。

  • 简单工厂模式的三个重要结构

①抽象基类:类中定义抽象一些方法,用以在子类中实现
②继承自抽象基类的子类:实现基类中的抽象方法
③工厂类:用以实例化对象

比如说我们工作中遇到的,MySQL实例化对象Session操作对象redis操作对象cache处理对象等等操作对象。

我们总会new mysql(),new PDO(),new Session(),new Redis(),都是重复的去做同一件事,是不是很麻烦,比较繁琐。所以引入工厂模式,使用工厂类来处理。

  • 我们为什么使用单例模式,解决了哪些痛点?

减轻繁琐的操作,直接将所有对象放入工厂类中,通过条件获取需要的实例化类。

我们一点点的来说明验证

  • 假设我们有以下几个类,我去这不就是几个简单类嘛 😸
/**
 * @desc mysql操作类
 * Class MySQL
 */
class MySQL
{
    public function __construct(array $config = [])
    {
        // TO DO
    }
}

/**
 * @desc PDO操作类
 * Class PDO
 */
class PDO
{
    public function __construct(array $config = [])
    {
        // TO DO
    }
}

/**
 * @desc Session操作类
 * Class Session
 */
class Session
{
    public function __construct(array $config = [])
    {
        // TO DO
    }
}

/**
 * @desc Redis操作类
 * Class Redis
 */
class Redis
{
    public function __construct(array $config = [])
    {
        // TO DO
    }
}
  • 那么我们每次使用时都需要new一下,下面酱紫😯
$mysqlObject = new MySQL();

$pdoObject = new PDO();

$sessionObject = new Session();

$redisObject = new Redis();

这样看上去挺麻烦的每次使用都需要new一次,一直来回的重复一个操作。像这种常用的类是不是可以放到工厂类里面,然后将接口暴露出去使用?问题来了,怎么暴露接口呢?

我们可以换一个思维想想,可不可以将这些将要实例化的类放到一个类里面,通过参数的传递来帮助我们自动实例化类,然后返回对象给我们?下面试一试

本来打算用上面四个类来演示,奈何网上所有教程都是加减乘除,所以按照程杰老师《大话设计模式》(以前看过的)书中的加减乘除举例,加上自己的设计比较符合PHP变成思想处理:

1,创建抽象基类base.php

<?php
/**
 * Created by Jonny li.
 * User:  82年的烂香蕉
 * Date: 2019/12/24
 * Time: 下午11:52
 * QQ: 2511221051@qq.com
 */

namespace liyangyang\DesignPatterns\SimpleFactory;

/**
 * @desc 加减乘除基类
 * Class Base
 * @package liyangyang\DesignPatterns\SimpleFactory
 */
abstract class Base
{
    /**
     * @desc 第一个数字
     * @var int
     */
    protected $numberOne = 0;

    /**
     * @desc 第二个数字
     * @var int
     */
    protected $numberTwo = 0;

    /**
     * @desc 计算结果
     * @access public
     * Author: 82年的烂香蕉
     * Date: 2019/12/24 下午11:55
     * @return mixed
     */
    abstract public function getResult();

    /**
     * @desc 设置第一个数值
     * @access public
     * Author: 82年的烂香蕉
     * Date: 2019/12/24 下午11:55
     * @param $number
     */
    public function setNumberOne($number)
    {
        $this->numberOne = $number;
        return $this;
    }

    /**
     * @desc 设置第二个数值
     * @access public
     * Author: 82年的烂香蕉
     * Date: 2019/12/24 下午11:55
     * @param $number
     */
    public function setNumberTwo($number)
    {
        $this->numberTwo = $number;
        return $this;
    }
}

2.加法类

<?php
/**
 * Created by Jonny li.
 * User:  82年的烂香蕉
 * Date: 2019/12/25
 * Time: 上午12:01
 * QQ: 2511221051@qq.com
 */

namespace liyangyang\DesignPatterns\SimpleFactory;

/**
 * @desc 数字求和类
 * Class Add
 * @package liyangyang\DesignPatterns\SimpleFactory
 */
class Add extends Base
{
    /**
     * @desc 两数求和
     * @access public
     * Author: 82年的烂香蕉
     * Date: 2019/12/25 上午12:02
     * @return int|mixed
     */
    public function getResult()
    {
        // TODO: Implement getResult() method.
        return $this->numberOne + $this->numberTwo;
    }
}

3.减法类

<?php
/**
 * Created by Jonny li.
 * User:  82年的烂香蕉
 * Date: 2019/12/25
 * Time: 上午12:03
 * QQ: 2511221051@qq.com
 */

namespace liyangyang\DesignPatterns\SimpleFactory;

/**
 * @desc 求差类
 * Class Subtraction
 * @package liyangyang\DesignPatterns\SimpleFactory
 */
class Subtraction extends Base
{
    /**
     * @desc 两数求差
     * @access public
     * Author: 82年的烂香蕉
     * Date: 2019/12/25 上午12:03
     * @return int|mixed
     */
    public function getResult()
    {
        // TODO: Implement getResult() method.
        return $this->numberOne - $this->numberTwo;
    }
}

4.乘法类

<?php
/**
 * Created by Jonny li.
 * User:  82年的烂香蕉
 * Date: 2019/12/25
 * Time: 上午12:04
 * QQ: 2511221051@qq.com
 */

namespace liyangyang\DesignPatterns\SimpleFactory;

/**
 * @desc 乘法类
 * Class Multiplication
 * @package liyangyang\DesignPatterns\SimpleFactory
 */
class Multiplication extends Base
{
    /**
     * @desc 求两数乘积
     * @access public
     * Author: 82年的烂香蕉
     * Date: 2019/12/25 上午12:05
     * @return float|int|mixed
     */
    public function getResult()
    {
        // TODO: Implement getResult() method.
        return $this->numberOne * $this->numberTwo;
    }
}

5.除法类

<?php
/**
 * Created by Jonny li.
 * User:  82年的烂香蕉
 * Date: 2019/12/25
 * Time: 上午12:06
 * QQ: 2511221051@qq.com
 */

namespace liyangyang\DesignPatterns\SimpleFactory;

/**
 * @desc 除法类
 * Class Division
 * @package liyangyang\DesignPatterns\SimpleFactory
 */
class Division extends Base
{
    /**
     * @desc 求两数相除
     * @access public
     * Author: 82年的烂香蕉
     * Date: 2019/12/25 上午12:05
     * @return float|int|mixed
     */
    public function getResult()
    {
        // TODO: Implement getResult() method.
        if ($this->numberTwo == 0) throw new \InvalidArgumentException('除数不能为零!');
        return $this->numberOne / $this->numberTwo;
    }
}
我们正常使用时酱紫的,new类,我们单独计算数据
<?php
/**
 * Created by Jonny li.
 * User:  82年的烂香蕉
 * Date: 2019/12/25
 * Time: 上午12:17
 * QQ: 2511221051@qq.com
 */

use liyangyang\DesignPatterns\SimpleFactory\Add;
use liyangyang\DesignPatterns\SimpleFactory\Subtraction;
use liyangyang\DesignPatterns\SimpleFactory\Multiplication;
use liyangyang\DesignPatterns\SimpleFactory\Division;

include_once __DIR__ . '/../vendor/autoload.php';

$operation1 = new Add();
echo $operation1->setNumberOne(1)->setNumberTwo(2)->getResult();

echo "<br>";

$operation2 = new Subtraction();
echo $operation2->setNumberOne(2)->setNumberTwo(2)->getResult();

echo "<br>";

$operation3 = new Multiplication();
echo $operation3->setNumberOne(3)->setNumberTwo(3)->getResult();

echo "<br>";

$operation4 = new Division();
echo $operation4->setNumberOne(4)->setNumberTwo(2)->getResult();

// 结果是
3 0 9 2

大家有没有注意,好麻烦的说,每次都要传**参数实例化再调用getResult**方法计算结果,有点坑爹的节奏,我们参数变化或者类名变化都要麻烦的去修改类,草,难受死。所以就有了工厂模式的出现,当当当当~~~~

Factory.php工厂类

<?php
/**
 * Created by Jonny li.
 * User:  82年的烂香蕉
 * Date: 2019/12/25
 * Time: 上午12:08
 * QQ: 2511221051@qq.com
 */

namespace liyangyang\DesignPatterns\SimpleFactory;

/**
 * @desc 简单工厂类
 * Class Factory
 * @package liyangyang\DesignPatterns\SimpleFactory
 */
class Factory
{
    /**
     * @desc 创建对象
     * @access public
     * Author: 82年的烂香蕉
     * Date: 2019/12/25 上午12:10
     * @param string $operator
     * @return Add|Division|Multiplication|Subtraction
     */
    public function createObject($operator = '+')
    {
        switch ($operator) {
            case '+':
                $result = new Add();
                break;
            case '-':
                $result = new Subtraction();
                break;
            case '*':
                $result = new Multiplication();
                break;
            case '/':
                $result = new Division();
                break;
            default:
                throw new \Exception('当前运算符不支持!');
        }
        return $result;
    }
}

下面玩一下哈,看着怎么调用:

<?php
/**
 * Created by Jonny li.
 * User:  82年的烂香蕉
 * Date: 2019/12/25
 * Time: 上午12:17
 * QQ: 2511221051@qq.com
 */

use liyangyang\DesignPatterns\SimpleFactory\Factory;

include_once __DIR__ . '/../vendor/autoload.php';

$factory = new Factory();

echo $factory->createObject()->setNumberOne(1)->setNumberTwo(2)->getResult();
似乎像那么回事了,有点意思。不过可以改造下,将createObject方法改成静态方法,这样是静态方法简单工厂,不需要创建实例,直接调用即可。

总结

上面这样的操作看起来视乎是解决了,总是重复 new 这一个操作但是也带来了另外一个隐患,就是,要是以后程序还会添加其他类实例化的操作,还要再去修改工厂类里面的switch case 语句,这样看起来还是有点麻烦,那么还有什么其他方法呢?
请看下一篇文章工厂方法模式 最详细的步骤介绍

github案例:https://github.com/82nlxj/php-design-patterns/tree/master/src/SimpleFactory

夜深了,今天不知不觉已经搞到凌晨了,好困好累,但是还是要坚持。坚持自己的目标,努力前行!也非常感谢大家们能看到这里,如果这个文章写得还不错,觉得「烂香蕉」我分享的有点东西的话 求点赞 求关注️ 求分享👥 求留言💬 对于鼓励我 非常有用!!!

(已完结)

豆浆大叔 豆浆大叔 资深PHP工程师@某一线大厂

写了 264486 字,被 3 人关注,共写了 75 篇笔记

(已更名,豆浆大叔)有理想的码农,不应该只探究人性的懒惰面,而是积极的去探索人生道路上的荆棘坎坷,努力提升自己完善自己!
推荐文章:
表情
  • [:821l1001:]
  • [:821l1002:]
  • [:821l1003:]
  • [:821l1004:]
  • [:821l1005:]
  • [:821l1006:]
  • [:821l1007:]
  • [:821l1008:]
  • [:821l1009:]
  • [:821l1010:]
  • [:821l1011:]
  • [:821l1012:]
  • [:821l1013:]
  • [:821l1014:]
  • [:821l1015:]
  • [:821l1016:]
  • [:821l1017:]
  • [:821l1018:]
  • [:821l1019:]
  • [:821l1020:]
  • [:821l1021:]
  • [:821l1022:]
  • [:821l1023:]
  • [:821l1024:]
  • [:821l1025:]
  • [:821l1026:]
  • [:821l1027:]
  • [:821l1028:]
  • [:821l1029:]
  • [:821l1030:]
  • [:821l1031:]
  • [:821l1032:]
  • [:821l1033:]
  • [:821l1034:]
  • [:821l1035:]
  • [:821l1036:]
  • [:821l1037:]
  • [:821l1038:]
  • [:821l1039:]
  • [:821l1040:]
  • [:821l1041:]
  • [:821l1042:]
  • [:821l1043:]
  • [:821l1044:]
  • [:821l1045:]
  • [:821l1046:]
  • [:821l1047:]
  • [:821l1048:]
  • [:821l1049:]
  • [:anger:]
  • [:applause:]
  • [:awkward:]
  • [:brokenheart:]
  • [:clown:]
  • [:confused:]
  • [:decline:]
  • [:diggingmouth:]
  • [:eyebrows:]
  • [:grinning:]
  • [:haha:]
  • [:ill:]
  • [:kiss:]
  • [:lascivious:]
  • [:laugh:]
  • [:love:]
  • [:lovely:]
  • [:rhinorrhea:]
  • [:smile:]
  • [:solid:]
  • [:strong:]
  • [:sweat:]
  • [:tearcollapse:]
  • [:tongue:]
  • [:uncomfortable:]
  • [:weak:]
  • [:worry:]
Tips:支持Markdown语法

0 个评论

抢座沙发~~~~
资深PHP工程师 @ 某一线大厂

登录

第三方账号登录:
GitHub
微信
微博