资讯专栏INFORMATION COLUMN

与工厂相关的设计模式之间的关系

aaron / 843人阅读

摘要:在标准的种设计模式中,与工厂相关的模式有种工厂方法模式和抽象工厂模式。在这里,要区分清楚的是工厂方法模式强调的是方法,而抽象工厂模式强调的是工厂,这是两个相关但又不相同的概念,就像做饭和厨房的区别,一个是谈动作,一个是谈空间。

在标准的23种设计模式中,与工厂相关的模式有2种:工厂方法模式(Factory method pattern)抽象工厂模式(Abstract factory pattern)。但现在很多介绍设计模式的文章又会提到一种简单工厂模式(Simple factory pattern),甚至还有静态工厂模式(Static factory pattern),那么这么多种与工厂相关的模式,它们之间是个什么关系呢?先来看图:

简单来说,简单工厂是静态工厂的升级,抽象工厂是简单工厂的升级,而不管什么工厂,它们最终都实现了工厂方法。在这里,要区分清楚的是工厂方法模式强调的是“方法”,而抽象工厂模式强调的是“工厂”,这是两个相关但又不相同的概念,就像“做饭”和“厨房”的区别,一个是谈动作,一个是谈空间。工厂方法是指的用工厂生产商品的方式来进行生产,而不管是简单工厂还是抽象工厂都是在讲对于工厂本身的管理。

没有工厂模式

举个例子来说,以前你是自己做饭吃:

$food = new Food();
静态工厂模式

自己一个人做饭吃也没什么不好,但是因为又要做饭,又要洗衣服,事情比较多,容易乱,所以不如把做饭这件事情外包出去,我就知道我们家旁边有一个小饭馆,去饭馆买饭吃,这就是一种松耦合。为了从简单入手,在这里,我们假定就是几种固定的食物,先不引入抽象商品的概念:

class StaticFactory
{
    public static function orderFood(): Food
    {
        return new Food();
    }
}

好了,至此我们有了一个静态工厂,下面就可以点餐了:

$food = StaticFactory::orderFood("chicken");

直接点餐,好简单。

简单工厂模式

但是这样想开一个连锁店,比如麦当劳这样的,怎么办呢?这时候我们就需要用到简单工厂模式:

class SimpleFactory
{
    public function orderFood(): Food
    {
        return new Food();
    }
}

和上面的方法几乎没有任何差别,唯一的差别只是少了一个static关键词,这样我们在点餐时,就需要先新建一个工厂,然后再点餐,这就是简单工厂:

$factory = new SimpleFactory();
$food = $factory->orderFood();
抽象工厂模式

现在我们不满足于只吃麦当劳了,我们还想吃肯德基,反正它们都是连锁店,提供的服务也都差不多,这时候就用到抽象工厂模式:

abstract class AbstractFactory
{
    abstract public function orderFood(): Food;
}

class MacDonald extends AbstractFactory
{
    public function orderFood(): Food
    {
        $food = new Food();
        $food->brand = "MacDonald";
        return $food;
    }
}

class KFC extends AbstractFactory
{
    public function orderFood(): Food
    {
        $food = new Food();
        $food->brand = "KFC";
        return $food;
    }
}

抽象工厂模式有约束了,凡是成为我工厂的,你们必须提供订餐这项基本服务。这样,我们在点餐的时候,点麦当劳就吃到了麦当劳的食物,点肯德基就吃到了肯德基的食物。

$factory1 = new MacDonald();
$food = $factory1->orderFood();
$factory2 = new KFC();
$food = $factory2->orderFood();
简单商品

我们都知道麦当劳也不只卖一种食品,可能卖鸡肉堡,也可能卖牛肉堡,既然要点餐,我们肯定要说明是点哪种汉堡,不可能他们给我们什么,我们就吃什么。你有很多种做法,我们先从最笨最简单的开始,大部分代码沿用上面的代码,只是在这里略加改动:

class MacDonald extends AbstractFactory
{
    public function orderChicken(): Chicken
    {
        $food = new Chicken();
        return $food;
    }

    public function orderBeef(): Beef
    {
        $food = new Beef();
        return $food;
    }
}

调用方法:

$factory = new MacDonald();
$chicken = $factory->orderChicken();
$beef = $factory->orderBeef();
换一种写法

但是这样是不是太笨了呢?我们完全可以写成一个方法:

class MacDonald extends AbstractFactory
{
    public function orderFood($type)
    {
        if ($type == "chicken") {
            $food = new Chicken();
        } elseif ($type == "beef") {
            $food = new Beef();
        }
        return $food;
    }
}

这样我们订餐的时候,只要这样就可以了:

$factory = new MacDonald();
$chicken = $factory->orderFood("chicken");
$beef = $factory->orderFood("beef");

当然,为了应付很多种食物,你不应该写if...else而应该写switch...case

抽象商品

最后,为了满足依赖反转原则(Dependency inversion principle)的要求,你实际上应该把所有的商品也抽象出来:

abstract class Food
{
    public $brand;
}

class Chicken extends Food
{
}

class Beef extends Food
{
}

abstract class AbstractFactory
{
    abstract public function orderFood(): Food;
}

class MacDonald extends AbstractFactory
{
    public function orderFood($type): Food
    {
        if ($type == "chicken") {
            $food = new Chicken();
        } elseif ($type == "beef") {
            $food = new Beef();
        }
        $food->brand = "MacDonald",
        return $food;
    }
}

class KFC extends AbstractFactory
{
    public function orderFood($type): Food
    {
        if ($type == "chicken") {
            $food = new Chicken();
        } elseif ($type == "beef") {
            $food = new Beef();
        }
        $food->brand = "KFC",
        return $food;
    }
}

$factory1 = new MacDonald();
$chicken1 = $factory1->orderFood("chicken");
$beef1 = $factory1->orderFood("beef");
$factory2 = new KFC();
$chicken2 = $factory2->orderFood("chicken");
$beef2 = $factory2->orderFood("beef");

同样还是那个鸡肉,同样还是那个牛肉,但是我们吃到了不同厂家的不同的食物。这就是抽象工厂+抽象商品的作用,最终你达到了完全解耦的目的。

工厂方法模式

说了这么半天,工厂方法模式在哪里?工厂方法模式其实已经完全溶化在每一个工厂当中,即使是最简单的静态工厂,只此一句话,就已经说明它在用工厂模式了:

return new Food();

简单来说就是:自己不去做,交给工厂去做,这就是工厂方法模式

我这里讲的只是一个入门,希望初学者不要上来就被那些高大上的名词砸晕,吓的不敢问津了。其实设计模式没那么复杂,没什么高大上的,只要理解了它们的本质,谁都可以轻松掌握,人人可以成为架构师。当然,更高深的理解还需要你去仔细钻研,也欢迎大家提出不同见解,共同学习,共同提高。在这里,我推荐一下这个链接,在这里你可以更加详细地了解其他模式。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/23314.html

相关文章

  • 第6章:可维护性软件构建方法 6.2可维护性设计模式

    摘要:抽象工厂模式将具有共同主题的对象工厂分组。对可重用性和可维护性设计模式的高层考虑创造性模式工厂方法模式也称为虚拟构造器意图定义一个用于创建对象的接口,但让子类决定实例化哪个类。 大纲 创造性模式 工厂方法模式创建对象而不指定要创建的确切类。 抽象工厂模式将具有共同主题的对象工厂分组。 Builder模式通过分离构造和表示来构造复杂的对象。 结构模式 Bridge将抽象从其实现中分...

    VioletJack 评论0 收藏0
  • “大话”设计模式

    摘要:抽象工厂模式是为了处理对象具有等级结构以及对象族的问题。单例设计模式单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类成为单例类。 导语:设计模式是无数码农前人在实际的生产项目中经过不断的踩坑、爬坑、修坑的经历总结出来的经验教训,经过抽象之后表达成的概念。能够帮助后来的设计者避免重复同样的错误或者弯路。我也抽空整理了一下设计模式,用自己的话总结了一下,自认...

    coordinate35 评论0 收藏0
  • 超全设计模式简介(45种)

    摘要:设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。设计模式的类型共有种设计模式。工厂模式工厂模式最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 该文建议配合 design-patterns-for-humans 中文版 一起看。 推荐阅读 超全的设计模式简介(45种) design-patterns-for-humans 中文版...

    wdzgege 评论0 收藏0
  • 超全设计模式简介(45种)

    摘要:设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。设计模式的类型共有种设计模式。工厂模式工厂模式最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 该文建议配合 design-patterns-for-humans 中文版 一起看。 推荐阅读 超全的设计模式简介(45种) design-patterns-for-humans 中文版...

    Betta 评论0 收藏0
  • JavaScript常用设计模式

    摘要:原文链接常用设计模式设计模式设计模式是一种在长时间的经验与错误中总结出来可服用的解决方案。用来模拟接口的相关操作我很帅通过适配器函数来调用目的我很帅学习资料听飞狐聊设计模式系列设计模式汤姆大叔 原文链接: JavaScript常用设计模式 设计模式 设计模式是一种在长时间的经验与错误中总结出来可服用的解决方案。 设计模式主要分为3类: 创建型设计模式:专注于处理对象的创建 Const...

    RyanHoo 评论0 收藏0

发表评论

0条评论

aaron

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<