head first python 實戰
下面將要介紹的就是書中的第一個設計模式:策略模式
書中以模擬鴨子應用問題作為實例,一款游戲應用中要求有各種各樣的鴨子。
先用繼承來實現了這一個應用,其設計如下:

這 個設計主要是以Duck類作為基類,后面所有的鴨子類均以此類派生而來,剛開始在應用還不是很復雜的時候,似乎還沒有什么問題,但當派生出來的類(鴨子的 類型)越來越多時,問題就出現了。并不是所有的鴨子都會飛的,比如像皮鴨子就不會飛。也不是所有的鴨子都會呱呱叫,也有鴨子吱吱叫。也許你會說,我可以在 派生類中重寫基類的方法,從而達到應用的要求,實現不同的鴨子有不同的叫法,不同的飛行方式。但是有一個問題不能解決,重寫函數并不應該改變原有函數的行 為,比如fly()這個函數,不能飛的鴨子就不應該有fly()這個函數存在。而如果我們只是重寫基類的fly()函數,看起來是不合適的。并且 quack()函數用于發出“呱呱叫”,而基類中定義了quack()就意味著所有的鴨子中都有quck(),如果現在要求鴨子“吱吱叫”,怎么辦呢?在 基類中添加一個"吱吱叫“的函數?那這樣又會影響到其它的子類。
如此看來,派生并不解決問題最好的辦法,或者說不能只用派生來解問題。
分析一下,得到以下設計原則:
-
針對接口編程,而不是實現編程
</li> -
分離應用中經常變化的部分
</li> </ul>
最終,我們分開了易于變化的部分,飛行行為和呱呱叫行為,設計出來的類圖如下:


我用python代碼實現如下:
'''
The first Design Pattern:
Strategy Pattern.
KeyNote:
Identify the aspects of your application that vary and separate them
from what stays the same.
'''
class FlyBehavior:
''' Interface class: FlyBehavior '''
def fly(self):
return
class FlyWithWing(FlyBehavior):
def fly(self):
print 'I am flying with wings!'
class FlyNoWay(FlyBehavior):
def fly(self):
print 'I cannot fly!'
class QuackBehavior:
''' Interface Behavior: QuackBehavior '''
def quack(self):
return
class Quack(QuackBehavior):
def quack(self):
print 'Quack!'
class Squeak(QuackBehavior):
def quack(self):
print 'Squeak'
class MuteQuack(QuackBehavior):
def quack(self):
print 'MuteQuack'
class Duck:
'''Base class: Duck. All ducks are inherent from this class'''
def __init__(self, flyParam, quackParam):
self.flyBehavior = flyParam
self.quackBehavior = quackParam
def performFly(self):
self.flyBehavior.fly()
def performQuack(self):
self.quackBehavior.quack()
def swim(self):
print 'All ducks can swim...'
return
def display(self):
return
class RedDuck(Duck):
def __init__(self, flyParam=FlyWithWing(), quackParam=MuteQuack()):
Duck.__init__(self, flyParam, quackParam)
def display(self):
print 'I am a red duck!'
return
class RubberDuck(Duck):
def __init__(self, flyParam=FlyNoWay(), quackParam=Quack()):
Duck.__init__(self, flyParam, quackParam)
def display(self):
print 'I am a rubber duck!'
duck = RedDuck()
duck.display()
duck.performFly()
duck.performQuack()
duck.swim()
duck = RubberDuck()
duck.display()
duck.performFly()
duck.performQuack()
duck.swim()