设计模式 - (抽象)工厂模式

本文以故事方式介绍工厂模式以及抽象工厂模式的一些知识,本文出现的人名为化名

周末闲来无事,小可爱给大漂亮说想吃烤红薯,让大漂亮做给小可爱吃,大漂亮有点为难了,一个堂堂七尺扣脚大汉,怎么会做烤红薯这种精细的事情呢。但是耐不住小可爱的执着,大漂亮于是决定现学现做,首先大漂亮去网上找了一个合适的教程,准备了一个烤箱和若干红薯。于是大张旗鼓的干了起来,A moment later, 香喷喷,热腾腾,稀软流油的红薯们就出箱了。小可爱就夸大漂亮能干,小可爱和大漂亮吃完这些红薯们,意犹未尽啊,突然心血来潮说,既然我们有了烤箱,我们再烤点其他的小食吧,比如说,烤蛋挞,烤曲奇..., 想想都美味。于是小可爱和大漂亮在烤箱食物的挟持下日渐"膨胀"。

这个烤的过程还是比较漫长枯燥的,大漂亮是一个程序猴子,就想这个过程是不是通过程序也能实现呢?古人云,勤劳致富,从面向对象的角度来看,万物皆可看对象,在用烤箱烤红薯的过程种,大漂亮和小可爱,烤箱,红薯,披萨,曲奇都可看作独立的对象,大漂亮小可爱可以用一个实体类表示,烤箱可以看做是一个加工工厂,用来加工的对象就是红薯,蛋挞,披萨,他们有以下共同点:

1. 都是食物

2. 都可以放在烤箱里烤

所以根据以上分析,大漂亮画出了的这个关系的类图

Oven是工厂角色,只要支持烤的食物都要在Oven里去做

IFood是抽象食物角色,所有的可烤食物都是属于食物,负责所有食物的烤的动作

Pizza和Tart则是具体食物,是Oven所烤的具体的对象

目前看起来貌似很不错哦,可以实现烤箱烤不同的食物,如果以后想烤其他食物,只需要增加具体食物类就行了,不过大漂亮一想,我用烤箱不仅仅用烤的功能的啊,它支持的功能我应该想用就能用啊。如果直接不把这些行为封装起来,既不满足面向对象的开闭原则也不好维护,于是又优化了一下类图如下所示:

 

 

如类图所示,和前面的类图的不同的是增加了一个抽象的接口类IBakeFactory, 这个类的作用就是定义这些具有公共行为的接口,正如上面小可爱所说,如果想用烤箱其他功能的话,直接实现这个抽象接口就可以啦,简单又方便。下面是这个类图的详细解释

IBakeFactory是抽象工厂角色 定义烤和支持烤哪些食物的接口

Oven是工厂角色,只要支持烤的食物都要在Oven里去做

IFood是抽象食物角色,所有的可烤食物都是属于食物,负责所有食物的烤的动作

Pizza和Tart则是具体食物,是Oven所烤的具体的对象

这下好了,通过上面的设计,小可爱想烤什么就只要指定食物就行了 打开烤箱就可以去烤它。

人的口腹之欲往往难以停留在某几种食物上,这时大漂亮突然有个疑问,这些食物只能用烤箱去烤吗? 会不会有其他的电器也可以用,于是大漂亮和小可爱仔细研究了一番,发现不仅仅是烤箱有上面的功能,像微波炉,空气炸锅也有类似的功能。如果不研究一下这些功能,以后烤箱不工作了不就完蛋了吗,特别是在急需裹腹的情况下肯定是难以忍受的。于是在大漂亮一番猛如虎的操作下,空气炸锅也安排上了,如果以后再增加微波炉等其他电器,只需把对应食物放进去烤就行了。于是大漂亮又更新了一下类图

优化后得步骤大概分为 

#准备食材 = 初始化产品
#选电器 = 初始化工厂
factory = oven.Oven(type(pizza.Pizza))
#开烤 = 做些什么
factory.bake()
#Define the bake factory interface
class IBakeFactory:
    def bake(self):
        pass
import IBakeFactory as bakeFactory
import Pizza as piz
import Tart as ta
"""
 Define the concrete factory
"""
class Oven(bakeFactory.IBakeFactory):
    """
    Initialize the class paramerts
    :param Self: this is instance of this class
    :param foodType: this is the specific food type, it can be Pizza or Tart or other supported type
    """
    def __init__(self, foodType):
        self._foodType = foodType
    
    """
    Do the bake operation according to the specific food
    """
    def bake(self):
        food = self.createFood()
        print('Bake %s' % food.getName())
    """
    Create the concrete food instance according to the input food type
    """
    def createFood(self):
        #Here create the Pizza instance
        if self._foodType == type(piz.Pizza):
            return piz.Pizza()
        #Here create the Tart instance
        if self._foodType == type(ta.Tart):
            return piz.Tart()
        else:
            return piz.Pizza()
import IFood as food
"""
Define the concrete Pizza class
"""
class Pizza(food.IFood):
    """
    Get the food name
    """
    def getName(self):
        return 'Pizza'
import IFood as food
"""
Define the Tart 
"""
class Tart(food.IFood):
    """
    Get the food name
    """
    def getName(self):
        return 'Tart'   
import Pizza as pizza
import Oven as oven
factory = oven.Oven(type(pizza.Pizza))
factory.bake()

这样一来,小可爱就不用关心怎么去烤了 只需要通过类似点餐的方式,等着吃就行了。

posted @ 2022-11-22 16:29  竹林溪风  阅读(51)  评论(0编辑  收藏  举报