一分鐘了解decorator pattern
Decorator Pattern 是 Python 中常見的一種設(shè)計(jì)模式,它允許你在不改變?cè)袑?duì)象的情況下,動(dòng)態(tài)地為對(duì)象添加功能。這個(gè)模式通常用于需要多個(gè)擴(kuò)展功能的場景,它可以優(yōu)雅地實(shí)現(xiàn)這些功能的添加和組合,而不需要寫大量的重復(fù)代碼。
?下面我們會(huì)用實(shí)例來詳細(xì)說明這個(gè)模式。
?在這個(gè)例子中,我們假設(shè)有一家咖啡店,賣各種咖啡,并且可以添加各種配料,比如牛奶、糖和巧克力醬等。我們需要設(shè)計(jì)一個(gè)程序來計(jì)算一杯咖啡的價(jià)格及其配料。
?首先,我們定義一個(gè)抽象基類 Beverage,它有兩個(gè)方法 get_description() 和 cost()。這個(gè)類會(huì)被所有飲料類繼承。
from abc import ABC, abstractmethod
?class Beverage(ABC):
? ? @abstractmethod
? ? def get_description(self):
? ? ? ? pass
? ? ?@abstractmethod
? ? def cost(self):
? ? ? ? pass
然后我們定義三個(gè)具體飲料類,分別是 Espresso、Latte 和 Cappuccino。它們都繼承自 Beverage,并實(shí)現(xiàn)了它們各自的價(jià)格和描述。
class Espresso(Beverage):
? ? def get_description(self):
? ? ? ? return 'Espresso'
? ? ?def cost(self):
? ? ? ? return 2.0
?class Latte(Beverage):
? ? def get_description(self):
? ? ? ? return 'Latte'
? ? ?def cost(self):
? ? ? ? return 3.0
?class Cappuccino(Beverage):
? ? def get_description(self):
? ? ? ? return 'Cappuccino'
? ? ?def cost(self):
? ? ? ? return 3.5
接下來,我們定義一個(gè)裝飾器類 CondimentDecorator,它也是一個(gè)飲料,但它有自己的價(jià)格和描述,用來增加飲料的配料。它繼承自 Beverage,并重寫了它的 get_description() 和 cost() 方法。
class CondimentDecorator(Beverage):
? ? def __init__(self, beverage):
? ? ? ? self.beverage = beverage
? ? ?@abstractmethod
? ? def get_description(self):
? ? ? ? pass
? ? ?def cost(self):
? ? ? ? return self.beverage.cost()
然后我們定義三個(gè)具體裝飾器類,分別是 Milk、Sugar 和 ChocolateSauce。它們都繼承自 CondimentDecorator,并實(shí)現(xiàn)了它們各自的價(jià)格和描述。它們的構(gòu)造函數(shù)需要一個(gè)被裝飾的飲料對(duì)象。
class Milk(CondimentDecorator):
? ? def __init__(self, beverage):
? ? ? ? super().__init__(beverage)
? ? ? ? ?self.price = 0.5
? ? ? ? ?self.description = ' with milk'
? ? ?def get_description(self):
? ? ? ? return self.beverage.get_description() + self.description
? ? ?def cost(self):
? ? ? ? return self.beverage.cost() + self.price
?class Sugar(CondimentDecorator):
? ? def __init__(self, beverage):
? ? ? ? super().__init__(beverage)
? ? ? ? ?self.price = 0.3
? ? ? ? ?self.description = ' with sugar'
? ? ?def get_description(self):
? ? ? ? return self.beverage.get_description() + self.description
? ? ?def cost(self):
? ? ? ? return self.beverage.cost() + self.price
?class ChocolateSauce(CondimentDecorator):
? ? def __init__(self, beverage):
? ? ? ? super().__init__(beverage)
? ? ? ? ?self.price = 0.8
? ? ? ? ?self.description = ' with chocolate sauce'
? ? ?def get_description(self):
? ? ? ? return self.beverage.get_description() + self.description
? ? ?def cost(self):
? ? ? ? return self.beverage.cost() + self.price
最后,我們來測試這個(gè)程序。我們創(chuàng)建了一個(gè) Espresso 對(duì)象,并加入 Milk 和 ChocolateSauce 兩個(gè)裝飾器對(duì)象。最后,我們輸出這杯咖啡的描述和價(jià)格。
espresso = Espresso()
?espresso_with_milk_chocolate = Milk(ChocolateSauce(espresso))
?print(f'Description: {espresso_with_milk_chocolate.get_description()}')
?print(f'Price: {espresso_with_milk_chocolate.cost()}')
運(yùn)行這個(gè)程序,我們可以看到最終的輸出為 “Description: Espresso with chocolate sauce with milk” 和 “Price: 3.3”,也就是 Espresso 加上 ChocolateSauce 和 Milk 的價(jià)格之和。
?這個(gè)例子中,我們使用 Decorator Pattern 來實(shí)現(xiàn)咖啡的配料功能,在不修改原有飲料類的情況下,動(dòng)態(tài)地添加和組合配料,使得代碼更加優(yōu)雅和易于擴(kuò)展。如果我們要添加更多的配料,我們只需要?jiǎng)?chuàng)建新的裝飾器類,并將它加入到飲料對(duì)象中即可。