装饰模式(Decorator),动态的给一个对象添加一些格外的职责,就增加功能来说,装饰模式比生成子类更灵活
Component是定义一个对象接口,可以给这些对象动态的添加职责。ConcreteComponent是定义了一个具体的对象,也可以给这个对象添加一些职责。Decorator,装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,是无需知道Decorator的存在的。治愈ConcreteDecorator就是具体的装饰对象,起到给Component添加职责的功能。
下面考虑《大话设计模式》中的例子:
写一个可以给人搭配不同的服饰的系统,可以换各种各样的衣服裤子的个人形象系统(简单点的,用控制台实现)
利用开放封闭原则(对于扩展是开放的(Open for extension),对于更改是封闭的(Closeed for modification))。无论模块是多么的’封闭’,都会存在一些无法对之封闭的变换。既然不可能完全封闭,设计人员必须对于他设计的模块应该对哪种变化封闭做出选择。必须先猜测出最有可能发生的变化种类,然后构造抽象来隔离那些变化。
装饰模式是利用SetComponent来对对象进行包装的。这样每个装饰对象的实现就和如何使用这个对象分离开了,每个装饰对象值关心自己的功能,不需要关心如何被添加到对象链当中。
Person类
class Person():
def __init__(self,name='',sex='男'):
self.name = name #person的姓名
self.sex = sex #性别
self.decoration = [cloth1,cloth8] #穿的衣服的list
def put_on(self,clothes):
genre = clothes.genre
priority = clothes.priority
self.del_the_same(genre,priority,1) #穿上先要脱掉已经穿上的和要穿的衣服外面的
self.decoration.append(clothes) #穿上衣服
def put_off(self,clothes):
genre = clothes.genre
priority = clothes.priority
self.del_the_same(genre,priority,0) #脱掉衣服
def del_the_same(self,genre,priority,flag):
i = 0
while 1:
try:
c = self.decoration[i]
except:
break
priorityF0 = c.priority == priority and flag == 0
priorityF1 = c.priority >= priority and flag == 1
if c.genre == genre and (priorityF0 or priorityF1):
del self.decoration[i]
else:
i += 1
def show_clothes(self):
string = self.name+'穿了 '
for c in self.decoration:
string += c.name + ' ,'
return string[:-2]
clothes类
class clothes():
def __init__(self,id=0,name='',priority=0,genre=''):
self.name = name #衣服的名字
self.id = id #衣服的id
self.genre = genre #衣服的类型
self.priority = priority #衣服穿的优先级,优先级小的穿在下面
衣柜
cloth1 = clothes(id = 1,name = "背心",priority = 0,genre = "上衣")
cloth2 = clothes(id = 2,name = "坎肩",priority = 0,genre = "上衣")
cloth3 = clothes(id = 3,name = "衬衫",priority = 1,genre = "上衣")
cloth4 = clothes(id = 4,name = "西服",priority = 2,genre = "上衣")
cloth5 = clothes(id = 5,name = "领带",priority = 2,genre = "配饰")
cloth6 = clothes(id = 6,name = "西裤",priority = 1,genre = "裤子")
cloth7 = clothes(id = 7,name = "七分裤",priority = 1,genre = "裤子")
cloth8 = clothes(id = 8,name = "短裤",priority = 1,genre = "裤子")
cloth9 = clothes(id = 9,name = "皮鞋",priority = 1,genre = "鞋")
cloth10 = clothes(id = 10,name = "休闲鞋",priority = 1,genre = "鞋")
cloth11 = clothes(id = 11,name = "凉鞋",priority = 1,genre = "鞋")
cloth12 = clothes(id = 12,name = "短袜",priority = 0,genre = "鞋")
cloth13 = clothes(id = 13,name = "长袜",priority = 0,genre = "鞋")
cloth14 = clothes(id = 14,name = "眼镜",priority = 1,genre = "配饰")
客户端示例
xc = Person(name = "小菜",sex = "男")
xc.put_on(cloth4)
xc.put_on(cloth1)
xc.put_on(cloth3)
xc.put_on(cloth10)
xc.put_on(cloth14)
xc.put_on(cloth6)
print unicode(xc.show_clothes(), "utf-8")
结果示例
E:\python>python Decoration.py
小菜穿了 背心 ,衬衫 ,休闲鞋 ,眼镜 ,西裤
装饰模式是为已有的功能动态地添加更多功能的一种方式,当系统需要新功能的时候,是向旧的类中添加新的代码。这些新加的代码通常装饰了原有的类的核心职责或主要行为,它们在主类中加入了新的字段,新的方法和新的逻辑,从而增加了主类的复杂度,而这些新加入的东西仅仅是为了满足一些只在某种特定情况下才会执行的特殊行为的需要。而装饰模式却提供了一个非常好的解决方案,它把每个要装饰的功能放在单独的类中,并让这个类包装它所要装饰的对象。因此,当需要执行特殊行为是,客户代码就可以在运行时根据需要选择地,按顺序地使用装饰功能包装了对象。