设计模式 #1: 策略模式
Posted on 2016-7-6 in Code
这是我有关图书 Head First 设计模式 的笔记,因为我刚开始学 Java,很多特性还不熟,所以这里选择用 Python 来实现。
定义
策略模式(strategy pattern)定义了算法簇,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
起始例子
class Duck(object):
def quack(self):
print "quack"
def swim(self):
print "swim"
def display(self):
raise NotImplementedError("abstract display")
class MallardDuck(Duck):
def display(self):
print "green"
class RedheadDuck(Duck):
def display(self):
print "red"
现在我们要让鸭子能飞,但并不是所有的鸭子都能飞,比如玩具橡皮鸭子,而且玩具玩具橡皮鸭子也不会呱呱叫(quack),而应该是吱吱叫(squeak)。
在超类添加方法并不是一个好的选择,因为它将fly
继承给了所有的子类。
问题
使用继承并不能很好的解决问题,因为鸭子的行为在子类里不断地改变,并且让所有的子类都有这些行为是不恰当的。
书中的解决办法
我们应该在鸭子类中包含设定行为的方法,这样就可以在”运行时“动态地改变鸭子的行为。
实际情况下,我们应该把以下类写到不同的文件中。
class FlyBehavior(object):
'''FlyBehavior interface class'''
def fly(self):
raise NotImplementedError('abstract FlyBehavior')
class FlyWithWings(FlyBehavior):
def fly(self):
print "I'm flying!!"
class FlyNoWay(FlyBehavior):
def fly(self):
print "I can't fly"
class QuackBehavior(object):
'''QuackBehavior interface class'''
def quack(self):
raise NotImplementedError('abstract QuackBehavior')
class Quack(QuackBehavior):
def quack(self):
print "Quack"
class Squeak(QuackBehavior):
def quack(self):
print "Squeak"
class MuteQuack(QuackBehavior):
def quack(self):
print "<< Silence >>"
class Duck(object):
'''Duck super class'''
def set_fly_behavior(self, fly_behavior):
self.fly_behavior = fly_behavior
def set_quack_behavior(self, quack_behavior):
self.quack_behavior = quack_behavior
def display(self):
raise NotImplementedError("abstract display")
def perform_fly(self):
self.fly_behavior.fly()
def perform_quack(self):
self.quack_behavior.quack()
def swim(self):
print "All ducks float, even decoys."
class MallardDuck(Duck):
def __init__(self):
super(MallardDuck, self).__init__()
self.set_fly_behavior(FlyWithWings())
self.set_quack_behavior(Quack())
def display(self):
print "green"
class RedheadDuck(Duck):
def __init__(self):
super(RedheadDuck, self).__init__()
self.set_fly_behavior(FlyWithWings())
self.set_quack_behavior(Quack())
def display(self):
print "red"
class RubberDuck(Duck):
def __init__(self):
super(RubberDuck, self).__init__()
self.set_fly_behavior(FlyNoWay())
self.set_quack_behavior(Squeak())
def display(self):
print "rubber"
if __name__ == '__main__':
# mini duck simulator
mallard = MallardDuck()
mallard.perform_quack()
mallard.perform_fly()
设计原则
- 找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。
- 针对接口编程,而不是针对实现编程 (注:接口是 Java 中的特性,Python 中并没有,但是我们可以有类来实现)。
- 多用组合,少用继承:“HAS-A”,而不是“IS-A”。