04.装饰模式

定义

  • 动态地给一个对象增加一些额外的职责,就拓展对象功能来说,装饰模式比生成子类的方式更为灵活。

装饰模式的抽象模型

类图

代码

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 类)。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇