PHP设计模式之简单工厂模式

先从简单工厂入门,不管是面试还是被他人面试,在问到设计模式的时候,大多数人都会提到工厂模式。毫无疑问,工厂相关的几种模式在设计模式中是最出名的也是应用比较广泛的一种模式。在GoF设计模式中也都是属于创建型的模式。

但是,能够说明白简单工厂工厂模式抽象工厂模式这三种模式的人还真能让面试官刮目相看。这里有个前提,是你真的能说明白,大部分人,包括在深入研究设计模式之前,我也没办法说清楚。不管是我去面试,还是面试其别人。当我面试别人的时候,能讲个大概也就差不多了。而我去面试的时候,也就是类似的讲个大概。经历不少挫折之后才有了想深入的研究研究设计模式的想法,于是便会产生这一系列的文章。从这篇简单工厂开始,我们一起再次深入的对设计模式进行学习。

当然,这里用的是PHP。

解释

简单工厂,也称静态工厂,不属于GoF23种设计模式。但是可以说是所有的设计模式中大家可能最容易理解,也可能在你的代码中早就已经用过不知道多少次的一种设计模式了。我们先从一个最最简单的代码段来看。

// Factory
class Factory
{
    public static function createProduct(string $type) : Product
    {
        $product = null;
        switch ($type) {
            case 'A':
                $product = new ProductA();
                break;
            case 'B':
                $product = new ProductB();
                break;
        }
        return $product;
    }
}

没错,核心点就是中间那段简单的switch代码,我们在返回值类型中固定为Product接口的实现。

在这段代码中,使用了PHP新特性,参数类型返回值类型**

产品接口和产品实现

// Products
interface Product
{
    public function show();
}

class ProductA implements Product
{
    public function show()
    {
        echo 'Show ProductA';
    }
}

class ProductB implements Product
{
    public function show()
    {
        echo 'Show ProductB';
    }
}

最后客户端的使用就很简单了

// Client
$productA = Factory::createProduct('A');
$productB = Factory::createProduct('B');
$productA->show();
$productB->show();

从以上代码可以看出,其实这里就是一个工厂类根据我们传入的字符串或者其他你自己定义的标识符,来返回对应的产品(Product对象)。

形象化一点的比喻:我是一个卖手机的批发商(客户Client,业务方),我需要一批手机(产品Product),于是我去让富士康(工厂Factory)来帮我生产。我下了订单($type变量)指明型号,然后富士康就给我对应型号的手机,然后我就继续我的工作了,和富士康的合作还真是挺愉快的。

这里比较规范的写法可能是所有产品都会去实现一个统一的接口,然后客户端只知道接口的方法统一调用即可。不规范的话也可以不使用接口,返回各种不同的对象,类似于外观(Facade)模式进行统一的门面管理。

简单工厂-讲解

源码地址:简单工厂基础类图实现

实例

场景:短信发送功能模块。现在我们使用了三个商家的,分别是阿里云、蝶信、极光的短信服务,在不同业务中可能使用不同的短信发送商,使用简单工厂可以方便的完成这个需求。

类图

简单工厂-消息发送

代码

<?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;
    }
}

Class MessageFactory {
    public static function createFactory($type){
        switch($type){
            case 'Ali':
                return new AliYunMessage();
            case 'BD':
                return new BaiduYunMessage();
            case 'JG':
                return new JiguangMessage();
            default:
                return null;
        }
    }
}

// 当前业务需要使用极光
$message = MessageFactory::createMessage('Ali');
echo $message->send('您有新的短消息,请查收');

源码地址:简单工厂实例-短信发送工厂

说明

  • createMessage一定要使用static?不一定,看自己业务情况决定,需要常驻的全部static,按需实例化的就new完了再正常->去调用
  • 三个message子类一定需要实现接口?也不一定,php本身就是弱类型语言,可以不去强制实现,但使用接口更加符合面向对象的规范(请参考多态),简单工厂本身其实是对多态的一种表述和应用
  • 当需要增加发送消息的渠道时,添加新类继承Message接口,实现send()方法,修改MessageFactory()中createFactory()方法里的switch
  • 思考上述修改违背了面向对象的什么原则?(提示:开放XX)
  • 实例中没有使用返回值类型?本身这也是新语法,对于老版本兼容来说可以不需要去写,但是如果公司技术栈已经升级到7以上的话,建议这种设计模式架构类的代码还是按照上方解释中的新特性写法去书写,也就是带上参数类型和返回值类型,更加的符合规范,也更容易理解
  • 实例中传错了$type返回NULL怎么办?亲,实际写代码的时候请处理好这个问题哟,返回一个默认的,或者上层捕获都是不错的解决方案,当然最好客户端那边提前判断好,没问题了再进工厂吧

下期看点

工厂方法模式,接着发短信,但这回我们让客户端换个姿势来发*

各自媒体平台均可搜索【硬核项目经理】

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,701评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,649评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,037评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,994评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,018评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,796评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,481评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,370评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,868评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,014评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,153评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,832评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,494评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,039评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,156评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,437评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,131评论 2 356

推荐阅读更多精彩内容