c#之装饰者模式
装饰者模式
1.概述:
动态的给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更加的灵活。
2.原理:
增加一个修饰的类来包裹原来的类,包裹的方式一般是通过将原来的对象作为修饰类的构造函数的参数。装饰类实现新的功能,但是,不需要用到新功能的地方,它可以直接调用原来的类中的方法,修饰类必须和原来的类有相同的接口。
3.模式中的角色
3.1:抽象构建(Component):定义一个抽象的接口,用以给这些对象动态的添加职责。
3.2:具体构建(ConcreteComponent):定义一个具体的对象,也可以给这个对象添加一些职责。
3.3:装饰类(Decorator):装饰抽象类,继承了Component,从外类来扩展Component类的功能。
3.4:具体装饰者(ConcretorDecorator):负责给构造对象添加职责。
4.模式解读:
5.应用实例的分析:
问题:装备大兵,无任何的装备时(核心功能)可以使用拳打脚踢,装备了步枪,可以使用步枪来进行射击,装备了重机枪,可以使用重机枪来进行射击,装备了火箭筒,可以使用火箭筒进行防空。
5.1装备类的定义:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 装饰模式 { /// <summary> /// 装备类 相当于Component /// </summary> public abstract class Equipment { public abstract void Attack(); } }
5.2:定义一个具体的对象,并且给对象添加一些职责:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 装饰模式 { /// <summary> /// 定义一个具体的对象,并且给对象添加一些职责。 /// </summary> class Soldier : Equipment { /// <summary> /// 没有任何武器装备下的核心的功能 /// </summary> public override void Attack() { Console.WriteLine("用拳脚进行攻击"); } } }
5.3:定义一个抽象的装备装饰类:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 装饰模式 { /// <summary> /// 装备装饰类(抽象类) /// </summary> public abstract class EquipDecorator : Equipment { protected Equipment Equipment; /// <summary> /// 增加装备 使用该方法来动态的给士兵增加装备 /// </summary> /// <param name="equipment">组件的设置</param> public void SetComponent(Equipment equipment) { this.Equipment = equipment; } /// <summary> /// 如果有装备 就用装备进行攻击 /// </summary> public override void Attack() { if (Equipment != null) { Equipment.Attack(); } } } }
5.4:各个子类的添加:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 装饰模式 { /// <summary> /// 步枪 /// </summary> public class RifleEquipment : EquipDecorator { public override void Attack() { base.Attack(); Console.WriteLine("步枪射击"); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 装饰模式 { /// <summary> /// 机枪 /// </summary> public class MachineGunEquipment : EquipDecorator { public override void Attack() { base.Attack(); Console.WriteLine("机枪扫射"); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 装饰模式 { /// <summary> /// 火箭炮射击 /// </summary> public class RocketGunEquipment : EquipDecorator { public override void Attack() { base.Attack(); Console.WriteLine("火箭炮射击"); } } }
5.5:客户端代码的调用:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 装饰模式 { class Program { static void Main(string[] args) { //定义新兵 Soldier soldier = new Soldier(); //三种装备 RifleEquipment rifleEquipment = new RifleEquipment(); MachineGunEquipment machineGunEquipment = new MachineGunEquipment(); RocketGunEquipment rocketGunEquipment = new RocketGunEquipment(); //将三种装备全部交给新兵 rifleEquipment.SetComponent(soldier); machineGunEquipment.SetComponent(rifleEquipment); rocketGunEquipment.SetComponent(machineGunEquipment); //攻击 除了拳脚功夫之外 新兵还可以使用步枪 机枪 火箭炮 最终执行的是rocketGunEquipment.Attcck(); rocketGunEquipment.Attack(); Console.ReadKey(); } } }
5.6:截图如下:
6:装饰模式的总结
总结:装饰模式是为已有功能动态的添加更多功能的一种方式。
当系统需要新的功能的时候,是向旧的类中添加新的代码,这些新的代码通常装饰了原来类的核心的职责或者主要的功能。但是这种做法的问题在于:他们在主类中加入了新的字段、新的方法或者新的逻辑之后,从而增加了主类的复杂性。而这些新加入的东西仅仅是为了满足一些特定的情况下才会执行的特殊的行为的需要。而装饰模式却提供了一个非常好的解决方案。它把每个要装饰的功能放在单独的类中,并让这个类包装它所要修饰的对象,因此当执行特殊的行为时,客户代码就可以在运行时根据需要有选择的、按顺序的使用装饰功能来进行包装对象了。
那么装饰模式的优点是:把类中的装饰功能从类中搬移出去,这样就可以简化原来的类。
所以这样做的最大的好处就是有效的把类的核心的职责和装饰功能区分开来,而且可以去除相关类中的重复的代码。