定义
- 动态地给一个对象增加一些额外的职责,就拓展对象功能来说,装饰模式比生成子类的方式更为灵活。
装饰模式的抽象模型
类图
代码
from abc import ABCMeta, abstractmethod
# 引入ABCMeta和abstractmethod来定义抽象类和抽象方法
class Person(metaclass=ABCMeta):
"""人"""
def __init__(self, name):
self._name = name
@abstractmethod
def wear(self):
print("着装:")
class Engineer(Person):
"""工程师"""
def __init__(self, name, skill):
super().__init__(name)
self.__skill = skill
def getSkill(self):
return self.__skill
def wear(self):
print("我是 " + self.getSkill() + "工程师 " + self._name, end=", ")
super().wear()
class Teacher(Person):
"教师"
def __init__(self, name, title):
super().__init__(name)
self.__title = title
def getTitle(self):
return self.__title
def wear(self):
print("我是 " + self._name + self.getTitle(), end=", ")
super().wear()
class ClothingDecorator(Person):
"""服装装饰器的基类"""
def __init__(self, person):
self._decorated = person
def wear(self):
self._decorated.wear()
self.decorate()
@abstractmethod
def decorate(self):
pass
class CasualPantDecorator(ClothingDecorator):
"""休闲裤装饰器"""
def __init__(self, person):
super().__init__(person)
def decorate(self):
print("一条卡其色休闲裤")
class BeltDecorator(ClothingDecorator):
"""腰带装饰器"""
def __init__(self, person):
super().__init__(person)
def decorate(self):
print("一条银色针扣头的黑色腰带")
class LeatherShoesDecorator(ClothingDecorator):
"""皮鞋装饰器"""
def __init__(self, person):
super().__init__(person)
def decorate(self):
print("一双深色休闲皮鞋")
class KnittedSweaterDecorator(ClothingDecorator):
"""针织毛衣装饰器"""
def __init__(self, person):
super().__init__(person)
def decorate(self):
print("一件紫红色针织毛衣")
class WhiteShirtDecorator(ClothingDecorator):
"""白色衬衫装饰器"""
def __init__(self, person):
super().__init__(person)
def decorate(self):
print("一件白色衬衫")
class GlassesDecorator(ClothingDecorator):
"""眼镜装饰器"""
def __init__(self, person):
super().__init__(person)
def decorate(self):
print("一副方形黑框眼镜")
# Test
#=======================================================================================================================
def testDecorator():
tony = Engineer("Tony", "客户端")
pant = CasualPantDecorator(tony)
belt = BeltDecorator(pant)
shoes = LeatherShoesDecorator(belt)
shirt = WhiteShirtDecorator(shoes)
sweater = KnittedSweaterDecorator(shirt)
glasses = GlassesDecorator(sweater)
glasses.wear()
print()
decorateTeacher = GlassesDecorator(WhiteShirtDecorator(LeatherShoesDecorator(Teacher("wells", "教授"))))
decorateTeacher.wear()
def testDecorator2():
tony = Engineer("Tony", "客户端")
sweater = KnittedSweaterDecorator(tony)
shirt = WhiteShirtDecorator(sweater)
glasses = GlassesDecorator(shirt)
glasses.wear()
# testDecorator()
# testDecorator2()
模型说明
- 设计要点
- 可灵活地给一个对象增加职责或拓展功能。
- 可增加任意多个装饰
- 装饰的顺序不同,可能产生不同的效果
- 优缺点
- 优点
- 使用装饰模式来实现扩展比使用继承更加灵活,它可以在不创造更多子类的情况下,将对象的功能加以扩展。
- 可以动态地给一个对象附加更多的功能。
- 可以用不同的装饰器进行多重装饰,装饰的顺序不同,可能产生不同的效果。
- 装饰类和被装饰类可以独立发展,不会相互耦合;装饰模式相当于继承的一个替代模式。
- 缺点
- 与继承相比,用装饰的方式拓展功能容易出错,排错也更困难。对于多次装饰的对象,调试寻找错误时可能需要逐级排查,较为烦琐。
- 优点
扩展——python 中的装饰器
简单装饰器
def loggingDecorator(func):
"""记录日志的装饰器"""
def wrapperLogging(*args, **kwargs):
print("开始执行 %s() ..." % func.__name__)
func(*args, **kwargs)
print("%s() 执行完成!" % func.__name__)
return wrapperLogging
def showMin(a, b):
print("%d、%d 中的最小值是:%d" % (a, b, a if a < b else b))
decoratedShowMin = loggingDecorator(showMin)
decoratedShowMin(2, 3)
执行结果
开始执行 showMin() ...
2、3 中的最小值是:2
showMin() 执行完成!
@语法糖
相当于原地替换
def loggingDecorator(func):
"""记录日志的装饰器"""
def wrapperLogging(*args, **kwargs):
print("开始执行 %s() ..." % func.__name__)
func(*args, **kwargs)
print("%s() 执行完成!" % func.__name__)
return wrapperLogging
@loggingDecorator
def showMin(a, b):
print("%d、%d 中的最小值是:%d" % (a, b, a if a < b else b))
showMin(2, 3)
执行结果
开始执行 showMin() ...
2、3 中的最小值是:2
showMin() 执行完成!
带参装饰器
def loggingDecoratorWithParam(app):
def loggingDecorator(func):
"""记录日志的装饰器"""
def wrapperLogging(*args, **kwargs):
print("%s: 开始执行 %s() ..." % (app, func.__name__))
func(*args, **kwargs)
print("%s: %s() 执行完成!" % (app, func.__name__))
return wrapperLogging
return loggingDecorator
# 相当于 showMin = loggingDecoratorWithParam(app="装饰器")(showMin)
@loggingDecoratorWithParam(app="装饰器")
def showMin(a, b):
print("%d、%d 中的最小值是:%d" % (a, b, a if a < b else b))
showMin(2, 3)
运行结果
装饰器: 开始执行 showMin() ...
2、3 中的最小值是:2
装饰器: showMin() 执行完成!
类装饰器
class ClassDecorator:
"""类装饰器,记录一个类被实例化的次数"""
def __init__(self, func):
self.__numOfCall = 0
self.__func = func
def __call__(self, *args, **kwargs):
self.__numOfCall += 1
obj = self.__func(*args, *kwargs)
print("创建%s的第%d个实例:%s" % (self.__func.__name__, self.__numOfCall, id(obj)))
return obj
# 相当于 MyClass = ClassDecorator(MyClass("Tony")) MyClass变成一个对象了,调用对象的__call__方法
@ClassDecorator
class MyClass:
def __init__(self, name):
self.__name = name
def getName(self):
return self.__name
tony = MyClass("Tony")
karry = MyClass("Karry")
print(id(tony))
print(id(karry))
运行结果
创建MyClass的第1个实例:1724052578064
创建MyClass的第2个实例:1724052578192
1724052578064
1724052578192
带参类装饰器
class ClassDecorator:
"""类装饰器,记录一个类被实例化的次数"""
def __init__(self, msg):
self.__numOfCall = 0
self.__msg = msg
def __call__(self, func):
def wrapper(*args, **kwargs):
self.__numOfCall += 1
obj = func(*args, *kwargs)
print("%s: 创建%s的第%d个实例:%s" % (self.__msg, func.__name__, self.__numOfCall, id(obj)))
return obj
return wrapper
@ClassDecorator("类装饰器")
class MyClass:
def __init__(self, name):
self.__name = name
def getName(self):
return self.__name
tony = MyClass("Tony")
karry = MyClass("Karry")
print(id(tony))
print(id(karry))
运行结果
类装饰器: 创建MyClass的第1个实例:2219679646544
类装饰器: 创建MyClass的第2个实例:2219679654224
2219679646544
2219679654224
应用场景
- 有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长时。
- 需要动态地增加或撤销功能时。
- 不能采用生成子类的方法进行扩充时,类的定义不能用于生成子类(如 Java 中的 final 类)。