装饰模式(Decorator)动态地给一个对象添加一个额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
Component是定义一个对象的接口,可以给这些对象动态添加职责。ConcreteCompoent是定义了一个具体的对象,也可以给这个对象添加一些职责。Decorator装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,是无需知道Decorator的存在的。至于ConcreteDecorator就是具体的装饰对象,起到给Component添加职责的功能
装饰模式结构图
在装饰模式中的各个角色有:
抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象。
具体构件(Concrete Component)角色:定义一个将要接收附加责任的类。
装饰(Decorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。
具体装饰(Concrete Decorator)角色:负责给构件对象"贴上"附加的责任。
代码结构
Person xc = new Person("小菜"); Console.WriteLine("\n第一种装扮:"); Sneakers pqx = new Sneakers(); BigTrouser kk = new BigTrouser(); TShirt dkx = new TShirt(); pqx.Decorate(xc); kk.Decorate(pqx); dkx.Decorate(kk); dkx.Show(); Console.WriteLine("\n第二种装扮:"); LeatherShoes px = new LeatherShoes(); Tie ld = new Tie(); Suit xz = new Suit(); px.Decorate(xc); ld.Decorate(px); xz.Decorate(ld); xz.Show(); Console.Read();
class Person { public Person() { } private string name; public Person(string name) { this.name = name; } public virtual void Show() { Console.WriteLine("装扮的{0}", name); } }
class Finery : Person { protected Person component; public void Decorate(Person component) { this.component = component; } public override void Show() { if (component!=null) { component.Show(); } } }
class LeatherShoes : Finery { public override void Show() { Console.Write("皮鞋"); base.Show(); } } //大T恤 class TShirt : Finery { public override void Show() { Console.Write("大T恤"); base.Show(); } } //垮裤 class BigTrouser : Finery { public override void Show() { Console.Write("垮裤"); base.Show(); } } //破球鞋 class Sneakers : Finery { public override void Show() { Console.Write("破球鞋"); base.Show(); } } //西装 class Suit : Finery { public override void Show() { Console.Write("西装"); base.Show(); } } //领带 class Tie : Finery { public override void Show() { Console.Write("领带"); base.Show(); } } //皮鞋
装饰模式利用SetComponent来对对象进行包装的,这样每个装饰的实现就和如何使用这个对象分离开了,每个装饰对象只关心自己的功能,不需要关心如何被添加到对象链当中
装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。
通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。
这种比继承更加灵活机动的特性,也同时意味着装饰模式比继承更加易于出错。
由于使用装饰模式,可以比使用继承关系需要较少数目的类。使用较少的类,当然使设计比较易于进行。但是,在另一方面,使用装饰模式会产生比使用继承关系更多的对象。更多的对象会使得查错变得困难,特别是这些对象看上去都很相像。
在以下情况下应当使用装饰模式:
需要扩展一个类的功能,或给一个类增加附加责任。
需要动态地给一个对象增加功能,这些功能可以再动态地撤销。
需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变得不现实。