PHP之工厂模式

工厂方法模式依赖于继承,因为对象创建 委托给 实现工厂方法创建对象 的子类

UML类图

在上面的URL类图中,Creator 需要 Product 对象的 Product1 类不直接实例化类。相反,它 Creator 指的是单独 factoryMethod() 创建一个产品对象,这使得Creator独立于哪个具体类被实例化。Creator可以重新定义要实例化的类的子类。在这个例子中,Creator1子类factoryMethod()通过实例化类来实现抽象Product1

上面简述一个工厂工作的流程,重点请看下面

1. 简单工厂模式

  • 模式定义:
    简单工厂模式(Simple Factory Pattern):又称为静态工厂方法(Static Factory Method)模式,之所以可以这么说,是因为简单工厂模式是通过一个静态方法来创建对象的。它属于类创建型模式。在简单工厂模式中,可以根据参数的不同返回返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
  • 模式结构
  1. Factory:工厂角色

    工厂角色负责实现创建所有实例的内部逻辑

  2. Product:抽象产品角色

    抽象产品角色是所创建的所有对象的父类,负责描述所有实例所共有的公共接口

  3. ConcreteProduct:具体产品角色

    具体产品角色是创建目标,所有创建的对象都充当这个角色的某个具体类的实例。

举个栗子

我们想创建一个工厂,这个工厂呢可以生产猫和狗!通常情况下我们会怎么做呢

interface animals // 抽象产品角色
{
    public function animal();
}
class Cat implements animals // 具体产品角色
{
    public function animal()
    {
        return "猫猫";
    }
}
class Dog implements animals // 具体产品角色
{
    public function animal()
    {
        return "狗狗";
    }
}
class Factory // 工厂角色
{
    public static function createAnimal($param)
    {
        $result = null;
        switch($param)
        {
            case 'cat':
                $result = new Cat();
                break;
            case 'dog':
                $result = new Dog();
                break;
        }
        return $result;
    }
}
echo  Factory::createAnimal("cat")->animal(); // 猫猫
echo  Factory::createAnimal("dog")->animal(); // 狗狗

上面的例子中所讲到的就是 简单工厂(静态工厂) <还请大佬批评>

简单工厂适用环境

  • 工厂类负责创建的对象比较少:由于创建的对象较少,不会造成工厂方法中的业务逻辑太过复杂。
  • 客户端只知道传入工厂类的参数,对于如何创建对象不关心:客户端既不需要关心创建细节,甚至连类名都不需要记住,只需要知道类型所对应的参数。

2. 工厂方法模式

工厂方法模式(Factory Method Pattern)又称为工厂模式,也叫虚拟构造器(Virtual Constructor)模式或者多态工厂(Polymorphic Factory)模式,它属于类创建型模式。在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。

举个栗子:

abstract class animals // 抽象产品类
{
    abstract public function animal();
}
class Cat extends animals // 具体产品类
{
    public function animal()
    {
        return "猫猫";
    }
}
class Dog extends animals // 具体产品类
{
    public function animal()
    {
        return "狗狗";
    }
}
interface Factory   // 抽象工厂类, 将对象的创建抽象成一个接口
{
    public function create();
}
class CatFactory implements Factory  // 继承工厂类, 用于实例化产品
{
    public function create()
    {
        return new Cat();
    }
}
class DogFactory implements Factory  // 继承工厂类, 用于实例化产品
{
    public function create()
    {
        return new Dog();
    }
}

class Client    // 具体操作类
{
    public function test()
    {
        $catResult = new CatFactory();
        echo $catResult->create()->animal();

        $DogResult = new DogFactory();
        echo $DogResult->create()->animal();
    }
}

$lala = new Client();
$lala->test(); //  猫猫狗狗

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

【工厂方法模式与简单工厂模式】

  • 工厂方法模式与简单工厂模式再结构上的不同不是很明显。工厂方法类的核心是一个抽象工厂类,而简单工厂模式把核心放在一个具体类上。
  • 工厂方法模式之所以有一个别名叫多态性工厂模式是因为具体工厂类都有共同的接口,或者有共同的抽象父类。
  • 当系统扩展需要添加新的产品对象时,仅仅需要添加一个具体对象以及一个具体工厂对象,原有工厂对象不需要进行任何修改,也不需要修改客户端,很好的符合了”开放-封闭”原则。而简单工厂模式在添加新产品对象后不得不修改工厂方法,扩展性不好。
  • 工厂方法模式退化后可以演变成简单工厂模式。

3. 抽象工厂模式

抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,属于对象创建型模式。

interface AnimalsFactory // 抽象工厂
{
    public function createCat(); // 生产一尾猫
    public function createDog(); // 生产一头狗 -_-
}

abstract class Cat  // 猫抽象
{
    abstract function getCat();
}
class ForeignCat extends Cat // 猫具体
{
    public function getCat()
    {
        return "外国布偶猫".PHP_EOL;
    }
}
class ChineseCat extends Cat
{
    public function getCat()
    {
        return "华夏猫".PHP_EOL;
    }
}

abstract class Dog
{
    abstract function getDog();
}
class ChineseDog extends Dog
{
    public function getDog()
    {
        return "中华国犬".PHP_EOL;
    }
}
class ForeignDog extends Dog
{
    public function getDog()
    {
        return "外国哈士奇".PHP_EOL;
    }
}

class CreateChineseAnimalFactory implements AnimalsFactory 
{
    public function createCat()
    {
        return new ChineseCat();
    }
    public function createDog()
    {
        return new ChineseDog();
    }
}
class CreateForeignAnimalFactory implements AnimalsFactory
{
    public function createCat()
    {
        return new ForeignCat();
    }
    public function createDog()
    {
        return new ForeignDog();
    }
}

$result = new CreateForeignAnimalFactory();
$ForeignCat = $result->createCat();
echo $ForeignCat->getCat(); // 布偶猫

$ForeignDog = $result->createDog();
echo $ForeignDog->getDog(); // 哈士奇

总结

区别

  1. 简单工厂模式(静态方法工厂模式) : 用来生产同一等级结构中的任意产品。(不能增加新的产品)

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

  3. 抽象工厂 :用来生产不同产品种类的全部产品。(不能增加新的产品,支持增加产品种类)

结语

使用工厂模式的好时机并不总是显而易见的。不要强制这样做,只有在构建复杂系统时才需要进行大量的抽象。你只要知道什么是抽象工厂,迟早你会发现一个真正的用例。good luck!

写于2018年5月25日

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