裝飾器模式
裝飾器模式,動態地給一個物件新增一些額外的職責,就增加功能來說,裝飾器模式比生成子類更為靈活。
程式碼示例
#coding:utf-8
#裝飾器模式
class Beverage():
name = ""
price = 0.0
type = "BEVERAGE"
def getPrice(self):
return self.price
def setPrice(self,price):
self.price = price
def getName(self):
return self.name
class coke(Beverage):
def __init__(self):
self.name = "coke"
self.price = 4.0
class milk(Beverage):
def __init__(self):
self.name = "milk"
self.price = 5.0
class drinkDecorator():
def getName(self):
pass
def getPrice(self):
pass
class iceDecorator(drinkDecorator):
def __init__(self,Beverage):
self.beverage = Beverage
def getName(self):
return self.beverage.getName() + " + ice"
def getPrice(self):
return self.beverage.getPrice() + 0.4
class sugarDecorator(drinkDecorator):
def __init__(self,Beverage):
self.beverage = Beverage
def getName(self):
return self.beverage.getName() + " + sugar"
def getPrice(self):
return self.beverage.getPrice() + 0.8
if __name__ == "__main__":
milk1 = milk()
print(milk1.getPrice(),milk1.getName())
iceMilk = iceDecorator(milk1)
print(iceMilk.getPrice(),iceMilk.getName())
cofe1 = coke()
print(cofe1.getPrice(),cofe1.getName())
sugarCofe = sugarDecorator(cofe1)
print(sugarCofe.getPrice(),sugarCofe.getName())
複製程式碼
程式碼解讀
該例子基於的需求:客戶點飲料系統,在使用者下單的過程中,可以對飲料進行相應的定製。
1、先定義了Beverage類,所有的飲料都是由該類繼承而來;
2、定義drinkDecorator類,所有需要新增的功能都是由該類繼承而來;
3、定義了iceDecorator類,對所點的飲料進行加冰,並且加冰後價格也需要增加;定義了sugarDecorator類,對所點的飲料進行加糖,並且加糖後價格也需要增加。
4、在客戶端呼叫時,先生成milk1例項,然後在對milk1加冰的過程中,在iceDecorator初始化的時候就將milk1例項傳入,在呼叫getName和getPrice時,呼叫milk1例項的方法後,接著處理milk1方法返回的結果,從而達到動態的更改getName和getPrice方法。
裝飾器模式應用場景: 需要擴充套件、增強或者減弱一個類的功能。
優點
1、裝飾器模式時繼承方式的一個替代方案,可以輕量級的擴充套件被裝飾物件的功能; 2、Python的裝飾器模式是實現AOP的一種方式,便於相同操作位於不同呼叫為止的統一管理。
缺點
1、多層裝飾器的除錯和維護較困難。
Python裝飾器模式的通用程式碼
def drugPrice(func):
def wrapper(self,*args,**kwargs):
print(self,args,kwargs)
self.price += 2
return func(self,*args,**kwargs)
return wrapper
class Food():
def __init__(self):
self.price = 1
@drugPrice
def getPrice(self):
return self.price
if __name__ == "__main__":
f = Food()
print(f.getPrice())
複製程式碼
**python 中的裝飾器編寫過程: **
先定義裝飾器函式
def drugPrice(func):
def wrapper(self,*args,**kwargs):
print(self,args,kwargs)
self.price += 2
return func(self,*args,**kwargs)
return wrapper
複製程式碼
該函式的呼叫過程如下: 當呼叫drugPrice(func)函式時,返回的是wrapper函式,該函式是func(self,*args,**kwargs),在wrapper(self,*args,**kwargs)的時候,就是呼叫的func(self,*args,**kwargs)函式,只不過此時還執行了print(self,args,kwargs);self.price += 2這段語句。
@drugPrice
def getPrice(self):
return self.price
複製程式碼
@drugPrice會被Python解析為getPrice=drugPrice(getPrice),此時可以理解為如下的執行順序
def getPrice(self):
return self.price
getPrice=drugPrice(getPrice)
複製程式碼
然後呼叫getPrice()函式就會把裝飾器裡面的內容執行完成。