Python 设计模式 - 装饰器模式

  • 简述

    装饰器模式允许用户在不改变其结构的情况下向现有对象添加新功能。这种类型的设计模式属于结构模式,因为这种模式充当现有类的包装器。
    这种模式创建了一个装饰器类,它包装了原始类并提供了额外的功能,使类方法签名保持不变。
    装饰器模式的动机是动态地附加对象的额外职责。
  • 如何实现装饰器设计模式

    下面提到的代码是如何在 Python 中实现装饰器设计模式的简单演示。插图涉及以课堂形式展示咖啡店。创建的咖啡类是一个抽象类,这意味着它不能被实例化。
    
    import six
    from abc import ABCMeta
    @six.add_metaclass(ABCMeta)
    class Abstract_Coffee(object):
       def get_cost(self):
          pass
       def get_ingredients(self):
          pass
       
       def get_tax(self):
          return 0.1*self.get_cost()
    class Concrete_Coffee(Abstract_Coffee):
       
       def get_cost(self):
          return 1.00
       
       def get_ingredients(self):
          return 'coffee'
    @six.add_metaclass(ABCMeta)
    class Abstract_Coffee_Decorator(Abstract_Coffee):
       
       def __init__(self,decorated_coffee):
          self.decorated_coffee = decorated_coffee
       
       def get_cost(self):
          return self.decorated_coffee.get_cost()
       
       def get_ingredients(self):
          return self.decorated_coffee.get_ingredients()
    class Sugar(Abstract_Coffee_Decorator):
       
       def __init__(self,decorated_coffee):
          Abstract_Coffee_Decorator.__init__(self,decorated_coffee)
       
       def get_cost(self):
          return self.decorated_coffee.get_cost()
       
       def get_ingredients(self):
          return self.decorated_coffee.get_ingredients() + ', sugar'
    class Milk(Abstract_Coffee_Decorator):
       
       def __init__(self,decorated_coffee):
          Abstract_Coffee_Decorator.__init__(self,decorated_coffee)
       
       def get_cost(self):
          return self.decorated_coffee.get_cost() + 0.25
       
       def get_ingredients(self):
          return self.decorated_coffee.get_ingredients() + ', milk'
    class Vanilla(Abstract_Coffee_Decorator):
       
       def __init__(self,decorated_coffee):
          Abstract_Coffee_Decorator.__init__(self,decorated_coffee)
       
       def get_cost(self):
          return self.decorated_coffee.get_cost() + 0.75
       
       def get_ingredients(self):
          return self.decorated_coffee.get_ingredients() + ', vanilla'
    
    咖啡店抽象类的实现是用一个单独的文件完成的,如下所述 -
    
    import coffeeshop
    myCoffee = coffeeshop.Concrete_Coffee()
    print('Ingredients: '+myCoffee.get_ingredients()+
       '; Cost: '+str(myCoffee.get_cost())+'; sales tax = '+str(myCoffee.get_tax()))
    myCoffee = coffeeshop.Milk(myCoffee)
    print('Ingredients: '+myCoffee.get_ingredients()+
       '; Cost: '+str(myCoffee.get_cost())+'; sales tax = '+str(myCoffee.get_tax()))
    myCoffee = coffeeshop.Vanilla(myCoffee)
    print('Ingredients: '+myCoffee.get_ingredients()+
       '; Cost: '+str(myCoffee.get_cost())+'; sales tax = '+str(myCoffee.get_tax()))
    myCoffee = coffeeshop.Sugar(myCoffee)
    print('Ingredients: '+myCoffee.get_ingredients()+
       '; Cost: '+str(myCoffee.get_cost())+'; sales tax = '+str(myCoffee.get_tax()))
    

    输出

    上述程序生成以下输出 -
    装饰图案