第 6 章 装饰模式
装饰模式总结:
装饰模式是为了已有功能动态得添加更多功能的一种方式。
当系统需要新功能时,是向旧的类中添加新的代码。这些新加的代码通常装饰了原有类的核心职责或主要行为。
在主类中加入新的字段,新的方法和新的逻辑,从而增加了主类的复杂度,
而这些新加入的东西仅仅是满足一些只在某种特定情况下才会执行的特殊行为的需要。而装饰模式却提供了一个非常好的解决方案,
它把每个要装饰的功能放在单独的类中,并让这个类包含它所要装饰的对象,
因此,当需要执行特殊行为是,客户代码就可以在运行是根据需要有选择、按顺序的使用装饰功能包装对象了。
装饰模式把类中的装饰功能从类中搬移去除,这样可以简化原有的类。
有效的把类的核心职责和装饰功能区分开了。而且可以去除相关类中重复的装饰逻辑。
Component是定义一个对象接口,可以给这些对象动态地添加职责。ConcreteComponent是定义了一个具体的对象,也可以给这个对象添加一些职责。
Decorator 装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,是无需知道Decorator的存在的。
至于ConcreteDecorator 就是具体的装饰对象,起到给Component添加职责的功能。
/// <summary> /// 要装饰的对象 /// </summary> public abstract class Component { /// <summary> /// 操作 /// </summary> public abstract void Operation(); } /// <summary> /// 具体要装饰的对象 /// </summary> public class ConcreteComponent : Component { public override void Operation() { Console.WriteLine("\n具体对象的操作"); } } /// <summary> /// 装饰类 /// </summary> public class Decorator : Component { protected Component component; /// <summary> /// 设置Component /// </summary> /// <param name="component"></param> public void SetComponent(Component component) { this.component = component; } /// <summary> /// 重写Operation(), 实际执行的是Component的Operation() /// </summary> public override void Operation() { if (component != null) { component.Operation(); } } } /// <summary> /// 具体装饰类A /// </summary> public class ConcreteDecoratorA : Decorator { /// <summary> /// 本类独有的功能:添加状态,以区别于ConcreteDecoratorB /// </summary> private string addState; public override void Operation() { ///首先运行原Component的Operation(),在执行本类的独有的功能,如addState,相当于对原Comoponent进行了修饰 base.Operation(); addState = "New State"; Console.WriteLine("具体装饰对象A的操作"); } } /// <summary> /// 具体装饰类B /// </summary> public class ConcreteDecoratorB : Decorator { public override void Operation() { ///首先运行原Component的Operation(),在执行本类的独有的功能,如addState,相当于对原Comoponent进行了修饰 base.Operation(); AddBehavior(); Console.WriteLine("具体装饰对象B的操作"); } private void AddBehavior() { Console.WriteLine("AddBehavior"); } }
客户端代码:
static void Main(string[] args) { /* *装饰的方式是:首先用ConcreteComponentA实例对象c, *然后用ConcreteDecoratorA的实例化对象a来装饰对象c, *再用ConcreteComponentB的实例化对象b 来装饰对象a, *最终执行b的Operation() */ ConcreteComponent c = new ConcreteComponent(); ConcreteDecoratorA a = new ConcreteDecoratorA(); ConcreteDecoratorB b = new ConcreteDecoratorB(); a.SetComponent(c); b.SetComponent(a); b.Operation(); Console.ReadLine(); }
结果:
*******************************************案例:小菜穿衣服************************************************************************
定义一个Person类:
public class Person { public Person() { } private string name; public Person(string name) { this.name = name; } public virtual void Show() { Console.Write("装扮的是:{0}", name); } }
定义一个服饰类:
/// <summary> /// 服饰类:用来装饰Person /// </summary> class Finery : Person { protected Person component; public void Decorate(Person component) { this.component = component; } public override void Show() { if (component != null) { // Console.WriteLine(component.ToString()); component.Show(); } } }
定义T恤服饰类:
/// <summary> /// 具体服饰类:T恤 /// </summary> class TShirts : Finery { public override void Show() { Console.Write("T恤 "); base.Show(); } }
定义服饰类裤子:
/// <summary> /// 具体服饰类:大裤子 /// </summary> class BigTrouser : Finery { public override void Show() { Console.Write("大裤子 "); base.Show(); } }
具体服饰类:皮鞋
/// <summary> /// 具体服饰类:皮鞋 /// </summary> class LeatherShoes : Finery { public override void Show() { Console.Write("皮鞋 "); base.Show(); } }
//。。。。其他具体服饰类省略
客户端调用:
Person xc = new Person("小菜"); Console.WriteLine("\n第一种装扮"); TShirts ts = new TShirts(); BigTrouser bt = new BigTrouser(); LeatherShoes lhs = new LeatherShoes(); ts.Decorate(xc); bt.Decorate(ts); lhs.Decorate(bt); lhs.Show();
调用结果: