本篇的装饰器模式不是讲解的python中的语法糖 @ 这个装饰器。而是讲解设计模式中的装饰器模式。网上不少的实现都是基于java和c++的。本文则使用python来实现,其中有些实现可能在python并不须要那样来写的,可是思路都是同样的。关于python @ 装饰器的使用我以后会再写一篇文章来介绍。html
你们知道咱们有的时候老是须要给给一个类或者一个对象增长一些行为。通常状况下使用继承和关联两种方式来实现。其中使用关联这种方式来实现并符合必定的设计规范的咱们称之为装饰器模式。接下来咱们首先会先介绍一下这两种方法,而后用python代码来分别实现这两种方法并比较他们之间的差别。java
通常状况下咱们都是经过继承来给一个或一群类来添加方法,经过继承使子类得到了父类的行为。虽然继承是一种适用普遍的方法,可是继承是一种静态行为,在代码编写阶段就已经固定,没法动态的控制一个类增长行为的种类和时间。python
咱们经过将一个A对象嵌入另外一个B对象里面,及将一个B对象里面的属性的值设置为A对象。经过在调用A对象的动做先后添加行为来给A对象增长功能。这种模式咱们称之为装饰器模式。 c++
“装饰模式以对客户透明的方式动态地给一个对象附加上更多的责任,换言之,客户端并不会以为对象在装饰前和装饰后有什么不一样。装饰模式能够在不须要创造更多子类的状况下,将对象的功能加以扩展。这就是装饰模式的模式动机。”[1] 设计模式
由于装饰器模式是在给对象增长责任。因此装饰器模式为对象结构型设计模式(对象是由于其是给对象而不是类增长责任,结构型模式就是描述如何将类或者对象结合在一块儿造成更大的结构,就像搭积木,能够经过简单积木的组合造成复杂的、功能更为强大的结构)。架构
一个饮料店里面卖茶和咖啡。 而且有冰块,糖和牛奶三种辅料能够添加。 咱们能够计算出一共有14中组合产品。而且每增长一种饮料就要增长7种组合产品。spa
class DrinkComponent(object): def get_price(self): pass def get_name(self): pass class TeaConcreteComponent(DrinkComponent): def __init__(self): self.__name = 'Tea' self.__price = 2 def get_price(self): return self.__price def get_name(self): return self.__name class CoffeeConcreteComponent(DrinkComponent): def __init__(self): self.__name = 'coffee' self.__price = 3 def get_price(self): return self.__price def get_name(self): return self.__name class IngredientsComponent(object): pass class IceConcreteComponent(IngredientsComponent): def add_ice_price(self): return 0.3 def add_ice_name(self): return '+Ice' class SugerConcreteComponent(IngredientsComponent): def add_suger_price(self): return 0.5 def add_suger_name(self): return '+Suger' class MilkConcreteComponent(IngredientsComponent): def add_milk_price(self): return 1 def add_milk_name(self): return '+Milk' class Tea_Milk(TeaConcreteComponent, MilkConcreteComponent): def get_price(self): return TeaConcreteComponent.get_price(self) + MilkConcreteComponent.add_milk_price(self) def get_name(self): return TeaConcreteComponent.get_name(self) + MilkConcreteComponent.add_milk_name(self) class Tea_Milk_Ice(TeaConcreteComponent, MilkConcreteComponent, IceConcreteComponent): def get_price(self): return TeaConcreteComponent.get_price(self) + MilkConcreteComponent.add_milk_price(self) \ + IceConcreteComponent.add_ice_price(self) def get_name(self): return TeaConcreteComponent.get_name(self) + MilkConcreteComponent.add_milk_name(self)\ + IceConcreteComponent.add_ice_name(self) if __name__ == '__main__': tea_milk = Tea_Milk() print tea_milk.get_name() print tea_milk.get_price() tea_milk_ice = Tea_Milk_Ice() print tea_milk_ice.get_name() print tea_milk_ice.get_price()
从图和代码中看首先咱们定义了DrinkComponent和IngredientsComponent即饮料和配料两个抽象类,并分别实现了具体的构建类。当咱们要产生一个产品的时候。经过继承不一样的具体构建类来实现。好比加冰加牛奶的茶。咱们经过继承茶、牛奶和冰块三个类来实现。能够看出若是要实现全部的类那么咱们须要14个子类来完成。支持多继承的语言才能这样实现若是是单继承的语言则须要经过多级继承来完成。不只冗余度增长并且复杂的多级继承关系是后期维护的泪。设计
class DrinkComponent(object): def get_price(self): pass def get_name(self): pass class TeaConcreteComponent(DrinkComponent): def __init__(self): self.__name = 'Tea' self.__price = 2 def get_price(self): return self.__price def get_name(self): return self.__name class CoffeeConcreteComponent(DrinkComponent): def __init__(self): self.__name = 'coffee' self.__price = 3 def get_price(self): return self.__price def get_name(self): return self.__name class IngredientsDecorator(DrinkComponent): def __init__(self, drink_component): self.drink_component = drink_component def get_price(self): pass def get_name(self): pass class IceConcreteDecorator(IngredientsDecorator): def get_price(self): return self.drink_component.get_price() + self.add_ice_price() def add_ice_price(self): return 0.3 def get_name(self): return self.drink_component.get_name() + self.add_ice_name() def add_ice_name(self): return '+Ice' class SugerConcreteDecorator(IngredientsDecorator): def get_price(self): return self.drink_component.get_price() + self.add_suger_price() def add_suger_price(self): return 0.5 def get_name(self): return self.drink_component.get_name() + self.add_suger_name() def add_suger_name(self): return '+Suger' class MilkConcreteDecorator(IngredientsDecorator): def get_price(self): return self.drink_component.get_price() + self.add_milk_price() def add_milk_price(self): return 1 def get_name(self): return self.drink_component.get_name() + self.add_milk_name() def add_milk_name(self): return '+Milk' if __name__ == '__main__': tea_milk = MilkConcreteDecorator(TeaConcreteComponent()) print tea_milk.get_name() print tea_milk.get_price() tea_milk_ice = IceConcreteDecorator(MilkConcreteDecorator(TeaConcreteComponent())) print tea_milk_ice.get_name() print tea_milk_ice.get_price()
DrinkComponent 是抽象构件类,它是具体构建类(*ConcreteComponent)和抽象装饰器类(IngredientsDecorator)的父类,主要定义了具体构建类的业务方法。以及让咱们在调用的时候能够统一的处理装饰前和装饰后的对象。方便咱们使用装饰器类装饰一个已经被装饰的具体构建如加糖(加冰(咖啡))。在关联关系中咱们主要说一下这个部分。 code
这是一个关联聚合关系。表示IngredientsDecorator是知道DrinkComponent类的存在的呢。这个你们能够这样理解。你在实现Concretecomponet的时候是不须要考虑IngredinetsDecorator的存在,由于你不会调用它的,也不继承它,也不知道你会被它调用。可是在设计实现ConcreteDecorator的时候你会在其属性中保持一个对DrinkComponet类型的类的引用。而且你会调用她的方法。这样你就要知道DrinkCompoent这个类里面都有什么方法及要知道DrinkComponent类的存在。在另外一种设计模式桥接模式这种关系正好是相反的。我以后再来写一篇关于桥接模式的介绍。component
咱们在代码中能够看到在IngredientsDecorator中也有get_price 和 get_name两种方法。这是为了保证在ConcreteComponent在被装饰器后仍是能够像没有被装饰那样被调哟个。而且咱们能够在调用的上面和下面添加功能以实现功能的加强。好比咱们在代码中是这样写的
def get_price(self): return self.drink_component.get_price() + self.add_milk_price()
咱们也能够将其改写为这样
def get_price(self): print 'add Milk' price = self.drink_component.get_price() new_price = price + self.add_milk_price() return new_price
咱们在调用被修饰的类的前面增长了一个功能打印 'add milk'这件事,并在获取了装饰的产品价格后给架构增长了一个牛奶的价格并将其返回。
经过装饰模式来扩展对象的功能比继承模式更灵活。构建和装饰器能够独立扩展,新增功能不须要添加大量的子类。可是装饰模式也产生了许多小对象,增长了排错的难度。
如下状况适合使用装饰器模式:
在不影响其余对象的状况下,以动态、透明的方式给单个对象添加职责。
须要动态地给一个对象增长功能,这些功能也能够动态地被撤销。
当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时。不能采用继承的状况主要有两类:第一类是系统中存在大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增加;第二类是由于类定义不能继承(如final类).[1]