Python装饰器详细操作教程
# Filename : example.py
# Copyright : 2020 By Bianchenghao6
# Author by : bianchenghao6.com
# Date : 2020-08-22
#又提到了那个快餐点餐系统,不过今天我们只以其中的一个类作为主角:饮料类。首先,回忆下饮料类:
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
#除了基本配置,快餐店卖可乐时,可以选择加冰,如果加冰的话,要在原价上加0.3元;
# 卖牛奶时,可以选择加糖,如果加糖的话,要原价上加0.5元。怎么解决这样的问题?
# 可以选择装饰器模式来解决这一类的问题。首先,定义装饰器类:
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.3
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.5
#构建好装饰器后,在具体的业务场景中,就可以与饮料类进行关联。以可乐+冰为例,示例业务场景如下:
if __name__=="__main__":
coke_cola=coke()
print("Name:%s"%coke_cola.getName())
print("Price:%s"%coke_cola.getPrice())
ice_coke=iceDecorator(coke_cola)
print("Name:%s" % ice_coke.getName())
print("Price:%s" % ice_coke.getPrice())
Name:coke
Price:4.0
Name:coke +ice
Price:4.3
对于扩展一个对象的功能,装饰模式比继承更加灵活,不会导致类的个数急剧增加 可以通过一种动态的方式来扩展一个对象的功能,通过配置文件可以在运行时选择不同的具体装饰类,从而实现不同的行为 可以对一个对象进行多次装饰 具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,且原有类库代码无须改变,符合开闭原则
使用装饰模式进行系统设计时将产生很多小对象,大量小对象的产生势必会占用更多的系统资源,在一定程度上影响程序的性能比继承更加易于出错,排错也更困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐
在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责 当不能采用继承的方式对系统进行扩展或者采用继承不利于系统扩展和维护时可以使用装饰模式。