今天难道有比较充裕的时间,忙里偷闲梳理一下工厂模式。
说起工厂模式,这可是一个很经典的模式。也是发展种类比较多的一种设计模式。单单在课上我们老师就给我们讲了三种不同的演化。而且这种设计模式的实用性非常好,也算简单易懂,可以说是程序猿入门必备的一种设计模式。
首先先说一个生活中的案例,也是工厂模式的一个经典的例子。
相比我们大多数的人都吃过西式的快餐,例如,KFC,麦当劳,汉堡王,赛百味之类的。这些快餐有一些类似的特点,就是它给提供单人套餐,双人套餐,家庭套餐之类的。比如leo在下和同学们中午玩累了,随便去一个KFC点一个全家桶,对于我们这种选择困难户来说显得既方便又简单。
然而给我们上课的老师喜欢云游四方,经常去外国去开会。在他眼中,外国快餐店给用户的选择性就非常的大。他给我们讲外国的赛百味,里面放多少奶油,放什么蔬菜,放什么肉,甚至烤成什么样子都是可以让顾客去选择的。
那么问题浮出水面,在程序设计中。我们做的最多的就是实例对象。试想一下,在一个快餐店里,如果来一个客人我们就new一个对象,那么客人一多我们岂不是要创建很多很多的对象。而且正如例子中的快餐店,如果都像外国Subway一样,什么东西都可以上客人去选择,那么情况肯定会变得更加的复杂。所以这个时候工厂模式就能解决这一个问题。
首先,工厂模式有三种版本的演化,分别是简单工厂,工厂模式,工厂方法。这里给出三种版本的简单解释:
1 简单工厂:对创建对象的代码进行简单的封装。
2 工厂方法:定义一个创建对象的接口,但是子类决定实例化哪一个,工厂方法让实例化推迟到子类去实现。
3 抽象工厂: 提供一个接口用于创建或依赖对象的家族而不需要明确指出具体类。
Then,我们怎么去一步一步的实现它呢?
首先我们先看简单工厂,这个方法和策略模式很像。精髓是:对创建对象的代码进行简单的封装。怎么做呢? 就是在程序中,我们要设计一个pizza的类,然后各式各样的具体的pizza去继承pizza。还要设计一个pizza的工厂,这个工厂可以实现order pizza的功能。然后呢在orderpizza中设定不同的场景,比如客人喜欢cheesepizza,你就给他new一个cheesepizza,客人喜欢clampizza,你就给他做一个clampizza就好了。
这种简单模式的类图和代码如下:
<span style="font-size:12px;">class pizza:
def prepare(self):
print 'prepare pizza'
def bake(self):
print'bake pizza'
def box(self):
print 'box pizza'
class cheesepizza(pizza):
def __init__(self):
self.name='cheesepizza'
def prepare(self):
print 'prepare '+ str(self.name)
def bake(self):
print'bake '+ str(self.name)
def box(self):
print 'box '+str(self.name)
class veggiepizza(pizza):
def __init__(self):
self.name='veggiepizza'
def prepare(self):
print 'prepare '+ str(self.name)
def bake(self):
print'bake '+ str(self.name)
def box(self):
print 'box '+str(self.name)
class clampizza(pizza):
def __init__(self):
self.name='clampizza'
def prepare(self):
print 'prepare '+ str(self.name)
def bake(self):
print'bake '+ str(self.name)
def box(self):
print 'box '+str(self.name)
class pepperoinpizza(pizza):
def __init__(self):
self.name='pepperoinpizza'
def prepare(self):
print 'prepare '+ str(self.name)
def bake(self):
print'bake '+ str(self.name)
def box(self):
print 'box '+str(self.name)
class pizzafactory:
def orderpizza(self,pizzaname):
if pizzaname=='cheesepizza':
pizza=cheesepizza()
pizza.prepare()
pizza.bake()
pizza.box()
elif pizzaname=='veggiepizza':
pizza=veggiepizza()
pizza.prepare()
pizza.bake()
pizza.box()
elif pizzaname=='clampizza':
pizza=clampizza()
pizza.prepare()
pizza.bake()
pizza.box()
elif pizzaname=='pepperoinpizza':
pizza=pepperoinpizza()
pizza.prepare()
pizza.bake()
pizza.box()
else:
print 'please order again'
if __name__=='__main__':
factory=pizzafactory()
factory.orderpizza('pepperoinpizza')
factory.orderpizza('clampizza')
factory.orderpizza('cheesepizza')
factory.orderpizza('veggiepizza')
</span>
*******************************************************************************************************************************
好了,这么一来有了一个最基本的版本了。那么看它是如何演进的。于是乎,我再抛出一个问题。像KFC呀,麦当劳呀,他们不可能只有一家对不对,像济南这种城市就有N家这种西式快餐店,那么说来,不同的门店,虽然标准相同,但是总会有一些例如味道不同。显然,一家简单工厂已经不能解决这些问题了。既然如此我们需要从工厂模式找寻这个问题的解决之道。
定义一个创建对象的接口,但是子类决定实例化哪一个,工厂方法让实例化推迟到子类去实现。这一段话怎么去理解,其实也是很简单的,就是工厂我也一开始不将它定义的这么死板,像pizza一样,我编一个pizzafactory的父类,然后呢,让真正的不同的pizzafactory去继承pizzafactory比如济南的KFC or 广东的KFC。这样,北方人口味比较重,当地会做一些偏咸的口味。南方人口味比较清淡,这样他们会做一些比较淡一点的口味。这样问题再一次得到了解决。
具体的类图和代码如下:
<span style="font-size:12px;">class pizza:
def prepare(self):
print 'prepare pizza'
def bake(self):
print'bake pizza'
def box(self):
print 'box pizza'
class beijingcheesepizza(pizza):
def __init__(self):
self.name='beijing cheesepizza'
def prepare(self):
print 'prepare '+ str(self.name)
def bake(self):
print'bake '+ str(self.name)
def box(self):
print 'box '+str(self.name)
class beijingveggiepizza(pizza):
def __init__(self):
self.name='beijing veggiepizza'
def prepare(self):
print 'prepare '+ str(self.name)
def bake(self):
print'bake '+ str(self.name)
def box(self):
print 'box '+str(self.name)
class beijingclampizza(pizza):
def __init__(self):
self.name='beijing clampizza'
def prepare(self):
print 'prepare '+ str(self.name)
def bake(self):
print'bake '+ str(self.name)
def box(self):
print 'box '+str(self.name)
class beijingpepperoinpizza(pizza):
def __init__(self):
self.name='beijing pepperoinpizza'
def prepare(self):
print 'prepare '+ str(self.name)
def bake(self):
print'bake '+ str(self.name)
def box(self):
print 'box '+str(self.name)
class jinancheesepizza(pizza):
def __init__(self):
self.name='jinan cheesepizza'
def prepare(self):
print 'prepare '+ str(self.name)
def bake(self):
print'bake '+ str(self.name)
def box(self):
print 'box '+str(self.name)
class jinanveggiepizza(pizza):
def __init__(self):
self.name='jinan veggiepizza'
def prepare(self):
print 'prepare '+ str(self.name)
def bake(self):
print'bake '+ str(self.name)
def box(self):
print 'box '+str(self.name)
class jinanclampizza(pizza):
def __init__(self):
self.name='jinan clampizza'
def prepare(self):
print 'prepare '+ str(self.name)
def bake(self):
print'bake '+ str(self.name)
def box(self):
print 'box '+str(self.name)
class jinanpepperoinpizza(pizza):
def __init__(self):
self.name='jinan pepperoinpizza'
def prepare(self):
print 'prepare '+ str(self.name)
def bake(self):
print'bake '+ str(self.name)
def box(self):
print 'box '+str(self.name)
class pizzafactory:
def orderpizza(self,pizzaname):
pass
class jinanpizzafactory(pizzafactory):
def orderpizza(self,pizzaname):
if pizzaname=='cheesepizza':
pizza=jinancheesepizza()
pizza.prepare()
pizza.bake()
pizza.box()
elif pizzaname=='veggiepizza':
pizza=jinanveggiepizza()
pizza.prepare()
pizza.bake()
pizza.box()
elif pizzaname=='clampizza':
pizza=jinanclampizza()
pizza.prepare()
pizza.bake()
pizza.box()
elif pizzaname=='pepperoinpizza':
pizza=jinanpepperoinpizza()
pizza.prepare()
pizza.bake()
pizza.box()
else:
print 'please order again'
class beijingpizzafactory(pizzafactory):
def orderpizza(self,pizzaname):
if pizzaname=='cheesepizza':
pizza=beijingcheesepizza()
pizza.prepare()
pizza.bake()
pizza.box()
elif pizzaname=='veggiepizza':
pizza=beijingveggiepizza()
pizza.prepare()
pizza.bake()
pizza.box()
elif pizzaname=='clampizza':
pizza=beijingclampizza()
pizza.prepare()
pizza.bake()
pizza.box()
elif pizzaname=='pepperoinpizza':
pizza=beijingpepperoinpizza()
pizza.prepare()
pizza.bake()
pizza.box()
else:
print 'please order again'
if __name__=='__main__':
factory=jinanpizzafactory()
factory.orderpizza('pepperoinpizza')
factory.orderpizza('clampizza')
factory.orderpizza('cheesepizza')
factory.orderpizza('veggiepizza')
factory=beijingpizzafactory()
factory.orderpizza('pepperoinpizza')
factory.orderpizza('clampizza')
factory.orderpizza('cheesepizza')
factory.orderpizza('veggiepizza')</span>
*******************************************************************************************************************************
根据上面的做法,我们已经能够成功创造出来各个地方的不同口味的pizza了。是不是有一点小小的激动。不过这还不是最终极的解决方案。Leo平时呢喜欢看武侠小说,最近小笼包版的神雕侠侣也是让Leo羞耻地吐了一阵老血。感叹的同时我想起来金庸老先生的原著,故事剧情到了是杨过在山洞中发现了独孤求败前辈的藏剑。一开始是一把锋利的好剑,之后呢是一把“宝剑不锋,大巧不工”的玄铁剑,最后居然是一把木剑。意思大体是,如果修炼到上乘,招式已在心中。花草树木皆可为剑,已经不因为外部的变化而改变战场的形式。
多么高深的境界~这和工厂模式的抽象工厂简直是异曲同工。那么我们根据金庸老先生的指点领会一下“提供一个接口用于创建或依赖对象的家族而不需要明确指出具体类”这一句话吧,23333!
感觉扯远了,咱们接上pizza的例子。虽然能这么设计,但是还是不自由。正如Leo的老师所见,外国的快餐店可以决定自己的汉堡里放几片肉,放几片菜。那么说来,所有的口味我们都可以让客户自己去点单。他们完全决定他们要吃什么东西。这也就是工厂模式的究极形式。
在这一个套路中,我们连原料都给大家暴露出来,客户在这里想放什么就给你放什么,想放多少我们就给你放多少,没有特定的口味,一切用户定义。这样实现完全自由选择的方式,实现对不同口味的客户进行最贴心的服务,而我们只给你们做好每一个地区不同风味的原料。这就是传说中的产品族,这里引用Leo老师上课说的一个很有意思的话,“如果你去找KFC的总店,你会很有意思的发现KFC总店并不是负责炸鸡的,也不是研究原料的,它真正做的事情就是做了一个肯德基的牌子,并且制定了一些看似非常非常简单的标准。但是当回过头来想肯德基怎么盈利的时候,又一个惊喜的发现是,钱就这么被他们赚过去了~”
最终的套路的类图和实现的代码如下:
<span style="font-size:12px;">class pizza:
def __init__(self,ingredientFactory):
self.ingredientFactory=ingredientFactory
def prepare(self):
pass
def bake(self):
print'bake pizza'
def box(self):
print 'box pizza'
class mypizza(pizza):
def __init__(self,ingredientFactory):
self.ingredientFactory=myingredientFactory()
def prepare(self):
self.ingredientFactory.createcheese(mycheese())
self.ingredientFactory.createclam(myclam())
self.ingredientFactory.createveggie(myveggie())
self.ingredientFactory.createpepperoin(mypepperoin())
class ingredientFactory:
def createcheese(self,cheese):
pass
def createclam(self,clam):
pass
def createveggie(self,veggie):
pass
def createpepperoin(self,pepperoin):
pass
class myingredientFactory(ingredientFactory):
def createcheese(self,cheese):
pass
def createclam(self,clam):
pass
def createveggie(self,veggie):
pass
def createpepperoin(self,pepperoin):
pass
class cheese:
def __init__(self):
pass
class mycheese(cheese):
def __init__(self):
self.name='leo\'s cheese'
print 'leo\'s cheese'
class clam:
def __init__(self):
pass
class myclam(clam):
def __init__(self):
self.name='leo\'s clam'
print 'leo\'s clam'
class veggie:
def __init__(self):
pass
class myveggie(veggie):
def __init__(self):
self.name='leo\'s veggie'
print 'leo\'s veggie'
class pepperoin:
def __init__(self):
pass
class mypepperoin(pepperoin):
def __init__(self):
self.name='leo\'s pepperoin'
print 'leo\'s pepperoin'
if __name__=='__main__':
pizza=mypizza(myingredientFactory())
pizza.prepare()
pizza.bake()
pizza.box()</span>
诶诶~写了好多呀~那么大家慢慢看吧~
*******************************************************************************************************************************