Python設計模式-裝飾器模式

北京-IT拾荒者發表於2018-09-03

裝飾器模式

裝飾器模式,動態地給一個物件新增一些額外的職責,就增加功能來說,裝飾器模式比生成子類更為靈活。

程式碼示例

#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()函式就會把裝飾器裡面的內容執行完成。

Python設計模式-裝飾器模式

識別圖中二維碼,領取python全套視訊資料

相關文章