穿什么有这么重要? 装饰模式
6.1 穿什么有这么重要?
6.2 小菜扮靓第一版
namespace 装饰模式 { class Program { static void Main(string[] args) { Person xc = new Person("小菜"); Console.WriteLine("\n第一种装扮:"); xc.WearTShirts(); xc.WearBigTrouser(); xc.WearSneakers(); xc.Show(); Console.WriteLine("\n第二种装扮:"); xc.WearSuit(); xc.WearTie(); xc.WearLeatherShoes(); xc.Show(); Console.Read(); } } class Person { private string name; public Person(string name) { this.name = name; } public void WearTShirts() { Console.Write("大T恤 "); } public void WearBigTrouser() { Console.Write("垮裤 "); } public void WearSneakers() { Console.Write("破球鞋 "); } public void WearSuit() { Console.Write("西装 "); } public void WearTie() { Console.Write("领带 "); } public void WearLeatherShoes() { Console.Write("皮鞋 "); } public void Show() { Console.WriteLine("装扮的{0}", name); } } }
6.3 小菜扮靓第二版
namespace 装饰模式 { class Program { static void Main(string[] args) { Person xc = new Person("小菜"); Console.WriteLine("\n第一种装扮:"); Finery dtx = new TShirts(); Finery kk = new BigTrouser(); Finery pqx = new Sneakers(); dtx.Show(); kk.Show(); pqx.Show(); xc.Show(); Console.WriteLine("\n第二种装扮:"); Finery xz = new Suit(); Finery ld = new Tie(); Finery px = new LeatherShoes(); xz.Show(); ld.Show(); px.Show(); xc.Show(); Console.Read(); } } class Person { private string name; public Person(string name) { this.name = name; } public void Show() { Console.WriteLine("装扮的{0}", name); } } abstract class Finery { public abstract void Show(); } class TShirts : Finery { public override void Show() { Console.Write("大T恤 "); } } class BigTrouser : Finery { public override void Show() { Console.Write("垮裤 "); } } class Sneakers : Finery { public override void Show() { Console.Write("破球鞋 "); } } class Suit : Finery { public override void Show() { Console.Write("西装 "); } } class Tie : Finery { public override void Show() { Console.Write("领带 "); } } class LeatherShoes : Finery { public override void Show() { Console.Write("皮鞋 "); } } }
需要把所需的功能按正确的顺序串联起来进行控制,
6.4 装饰模式
动态的给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活,
namespace 装饰模式 { class Program { static void Main(string[] args) { ConcreteComponent c = new ConcreteComponent(); ConcreteDecoratorA d1 = new ConcreteDecoratorA(); ConcreteDecoratorB d2 = new ConcreteDecoratorB(); d1.SetComponent(c); d2.SetComponent(d1); //d1包装c,d2包装d1,执行d2, d2.Operation(); Console.Read(); } } //定义一个对象接口,可以给这些对象动态的添加职责, abstract class Component { public abstract void Operation(); } //定义一个具体对象,也可以给这个对象添加职责, class ConcreteComponent : Component { public override void Operation() { Console.WriteLine("具体对象的操作"); } } //装饰抽象类, abstract class Decorator : Component { protected Component component; public void SetComponent(Component component) //设置Component, { this.component = component; } public override void Operation() //重写Operation,实际执行的是Component的Operation, { if (component != null) { component.Operation(); } } } //具体的装饰对象,起到给Component添加职责的功能, class ConcreteDecoratorA : Decorator { private string addedState; public override void Operation() { base.Operation(); //首先运行原Component的Operation,再执行本类功能,相当于对原Component进行了装饰, addedState = "New State"; Console.WriteLine("具体装饰对象A的操作"); } } class ConcreteDecoratorB : Decorator { public override void Operation() { base.Operation(); //同上 AddedBehavior(); Console.WriteLine("具体装饰对象B的操作"); } private void AddedBehavior() //本类独有 { } } }
装饰模式是利用SetComponent来对对象进行包装的,这样每个装饰对象的实现就和如何使用这个对象分离开了,每个装饰对象只关心自己的功能,不需要关心如何被添加到对象链当中,
6.5 小菜扮靓第三版
namespace 装饰模式 { class Program { static void Main(string[] args) { Person xc = new Person("小菜"); Console.WriteLine("\n第一种装扮:"); Sneakers pqx = new Sneakers(); BigTrouser kk = new BigTrouser(); TShirts dtx = new TShirts(); pqx.Decorate(xc); kk.Decorate(pqx); dtx.Decorate(kk); dtx.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.WriteLine("\n第三种装扮:"); Sneakers pqx2 = new Sneakers(); LeatherShoes px2 = new LeatherShoes(); BigTrouser kk2 = new BigTrouser(); Tie ld2 = new Tie(); pqx2.Decorate(xc); px2.Decorate(pqx); kk2.Decorate(px2); ld2.Decorate(kk2); ld2.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 TShirts : 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(); } } class LeatherShoes : Finery { public override void Show() { Console.Write("皮鞋 "); base.Show(); } } }
6.6 装饰模式总结
装饰模式是为已有功能动态的添加更多功能的一种方式,
系统需要新功能时,是向旧类中添加新代码,这些新代码通常装饰了原有类的核心职责或主要行为,如用西装或嘻哈服来装饰小菜,这种做法的问题在于,在主类中添加了新字段,新方法和新逻辑,从而增加了主类的复杂度,就像起初的“人”类,这些新加入的东西仅仅是为了满足一些只在某种特定情况下才会执行的特殊行为的需要,装饰模式把每个要装饰的功能放在单独的类中,并让这个类包装它所要装饰的对象, 因此,当需要执行特殊行为时,客户代码就可以在运行时根据需要有选择的,按顺序的使用装饰功能包装对象了,
装饰模式的优点就是,把类中的装饰功能从类中搬移去除,这样可以简化原有的类,有效的把类的核心职责和装饰功能区分开了,而且可以去除相关类中重复的装饰逻辑,