平时大家上班都很累,为了增加工作中的欢乐气氛,黄页组准备搞个游戏。
游戏的名字是把大象关进冰箱。游戏很简单,需要把指定的物品放进冰箱。
我们都知道,把大象放进冰箱,分3步。
第一步,打开冰箱门,第二步,把大象放进去,第三步,关上冰箱。
但是,首先你的有一头大象,所以,人为又加了第零步,准备一只大象。
为了保证游戏的欢乐性,我们规定游戏者,在第二步把大象放进去的时候,需要有不同的表情动作等。
好,我并没有逗你玩。
游戏开始。
大雁同学很有兴趣。于是,我们编写一个简单的程序来实现这个过程。
写一个类.实现这个过程。
class PlayerDaisy: s_object = None def __init__(self): pass def set_up(self): PlayerDaisy.s_object = "大象" print '准备一只大象 daisy 去了泰国买了一只', PlayerDaisy.s_object def step_one(self): print '打开冰箱门' def step_two(self): print '蹦蹦跳跳哭着,把大象放进冰箱' def step_three(self): print '关上冰箱门'
if __name__ == "__main__": daisy = PlayerDaisy() daisy.set_up() daisy.step_one() daisy.step_two() daisy.step_three()
运行结果:
菜菜,觉得挺好玩的于是也加入了游戏...
于是,我们继续编写代码
class PlayerYicai: s_object = None def __init__(self): pass def set_up(self): PlayerDaisy.s_object = "老虎" print 'caicai 去了孟加拉买了一只', PlayerYicai.s_object def step_one(self): print '打开冰箱门' def step_two(self): print '歪歪扭扭笑着,把%s进冰箱' % PlayerYicai.s_object def step_three(self): print '关上冰箱门'
然后高峰,羞羞....都觉得挺好玩的,都纷纷加入了游戏...
越来越多的人加入,于是,我们开始抄代码。。。复制,粘贴
情况有所不妙,抄得过程中,高峰忘记抄了step1, 没打开冰箱门。
结果鳄鱼,没法放进去了.....
羞羞忘记抄step3了,狮子,关进去,又出来了...
类似的情况越来越糟。
DRY:don't repeat yourself.
在这个缤纷的世界上,是否有东西,会永远不变?
谚语:
the only thing in the world that doesn't change is change itself.
所以,please DRY,也叫 DIE (duplication is evil)
上面的话,是我抄的。
重复是丑陋的,也是bug的温床。
ok, 那么我们可以尝试用模板方法模式来避免这种坏味道。
1. 概述
定义一个操作中的算法的骨架,而将步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义算法的某些特定步骤。
2. 模式中的角色
2.1 抽象类(AbstractClass):实现了模板方法,定义了算法的骨架。
2.2 具体类(ConcreteClass):实现抽象类中的抽象方法,已完成完整的算法。
3. 模板方法类图:
那么,我们尝试改造代码。
首先,需要写一个基类。
由于开冰箱门和关冰箱门是固定的。所以定义抽象方法或虚方法第二步放物品。和准备物品。
我们还需定义一个公共的playgame方法。规定游戏的步骤,这样的话,就再也不会抄错啦。
子类必须实现父类的抽象方法。父类又定义了完成游戏的模板。
简直完美。
在python中 abc 模块(咦?为啥用个卫生巾的名字)实现了 抽象类和方法的功能。(我也是bing后才知道的)
使用了
@abc.abstractmethod装饰器的方法必须要在子类中实现
代码如下:
class PlayerBase(object): s_object = "未知东东" def __init__(self): pass @abc.abstractmethod def set_up(self): pass def step_one(self): print '打开冰箱门' @abc.abstractmethod def step_two(self): pass def step_three(self): print '关上冰箱门' def play_game(self): self.set_up() self.step_one() self.step_two() self.step_three()
继承类。
class PlayerDaisy2(PlayerBase): def __init__(self): pass def set_up(self): PlayerDaisy.s_object = "大象" print '准备物品 去了买了一只', PlayerDaisy.s_object def step_two(self): print '%s,把%s放进冰箱' % ('蹦蹦跳跳哭着', PlayerDaisy.s_object)
if __name__ == "__main__": daisy = PlayerDaisy2() daisy.play_game()
运行结果:
恩恩。。。太完美了。。。
模板方法模式就到这里。。
花了我几个小时写这篇文章。
构思都是在地铁上。
to be continued