什么是装饰模式
动态地给一个对象增加一些额外的职责,就拓展对象功能来说,装饰模式比生成子类的方式更加灵活。
设计要点
1、可灵活地给一个对象增加职责或拓展功能;
2、克增加任意多个装饰;
3、装饰的顺序不同,可能产生不同的效果;
代码实现
有一个小孩类,最初是什么技能都没有。通过学习后,学会了自己吃饭,走路,阅读等。以此为案例,使用装饰模式的设计思想实现。
from abc import ABCMeta, abstractmethod
class Ability(metaclass=ABCMeta):
"""能力抽象类"""
def __init__(self, child):
self.child = child
@abstractmethod
def get_skill(self):
pass
class Child:
"""小孩类"""
def __init__(self, name):
self.name = name
def learnning(self):
"""拥有学习技能"""
print("我是{0},我长大过程中要学习很多技能...".format(self.name))
上述是两个主类,一个是小孩类,一个是能力抽象类;
增加一个学会自己吃饭的技能:
class Eat(Ability):
def __init__(self, child):
super().__init__(child)
def get_skill(self):
self.learnning()
def learnning(self):
self.child.learnning()
print("我正在学习如何自己吃饭?")
print("我能够一个人吃饭啦!")
执行代码:
if __name__ == "__main__":
tony = Child("Tony")
can_eat = Eat(tony)
can_eat.get_skill()
结果为:
我是Tony,我长大过程中要学习很多技能...
我正在学习如何自己吃饭?
我能够一个人吃饭啦!
增加一个会走路的技能:
class Walk(Ability):
def __init__(self, child):
super().__init__(child)
def get_skill(self):
self.learnning()
def learnning(self):
self.child.learnning()
print("我正在学习如何自己走路?")
print("我学会走路啦!")
执行代码:
if __name__ == "__main__":
tony = Child("Tony")
can_eat = Eat(tony)
can_walk = Walk(can_eat)
can_walk.get_skill()
结果为:
我是Tony,我长大过程中要学习很多技能...
我正在学习如何自己吃饭?
我能够一个人吃饭啦!
我正在学习如何自己走路?
我学会走路啦!
增加一个会阅读的技能:
class Reading(Ability):
def __init__(self, child):
super().__init__(child)
def get_skill(self):
self.learnning()
def learnning(self):
self.child.learnning()
print("我正在学习如何阅读?")
print("我学会阅读啦!")
执行代码:
if __name__ == "__main__":
tony = Child("Tony")
can_eat = Eat(tony)
can_walk = Walk(can_eat)
can_read = Reading(can_walk)
can_read.get_skill()
结果为:
我是Tony,我长大过程中要学习很多技能...
我正在学习如何自己吃饭?
我能够一个人吃饭啦!
我正在学习如何自己走路?
我学会走路啦!
我正在学习如何阅读?
我学会阅读啦!
像这样,增加一项技能,并不需要修改已有功能。需要改动的仅仅是:新增的技能代码以及代码装饰的顺序而已;
优缺点
1、使用装饰模式来实现扩展比使用继承更加灵活,它可以在不创造更多子类的情况下,将对象的功能加以扩展;
2、可以动态地给一个对象附加更多的功能;
3、可以用不同的装饰器进行多重装饰,装饰的顺序不同,可能产生不同的效果;
4、装饰类和被装饰类可以独立发展,不会相互耦合;装饰模式相当于继承的一个替代模式;