装饰模式
概述
不必改变原类文件和使用继承的情况下,动态地给一个对象添加一些额外的职责,通过创建一个包装对象,也就是装饰来包裹真实的对象就增加功能来说,装饰模式比生成子类更为灵活。
动态地扩展一个对象的功能。并且支持多个装饰器的嵌套使用。
结构图
代码
原抽象
/// <summary> /// 抽象构件 /// </summary> public abstract class Component { public abstract void Operation(); }
待装饰对象
/// <summary> /// 具体对象待扩展的对象 /// </summary> public class ConcreteComponent : Component { public override void Operation() { Console.WriteLine("具体对象的操作"); } }
装饰器
/// <summary> /// 装饰抽象类 /// </summary> public abstract class Decorator : Component { protected Component component; public void SetComponent(Component component) { this.component = component; } public override void Operation() { if (component != null) { component.Operation(); } } }
具体装饰对象
/// <summary> /// 具体装饰行为A /// </summary> public class ConcreteDecoratorA : Decorator { private string addedState; public override void Operation() { base.Operation(); addedState = "New State"; Console.WriteLine("具体装饰对象A的操作"); } }
/// <summary> /// 具体装饰行为B /// </summary> public class ConcreteDecoratorB : Decorator { public override void Operation() { base.Operation(); AddedBehavior(); Console.WriteLine("具体装饰对象B的操作"); } private void AddedBehavior() { } }
主程序
static void Main(string[] args) { ConcreteComponent c = new ConcreteComponent(); ConcreteDecoratorA d1 = new ConcreteDecoratorA(); ConcreteDecoratorB d2 = new ConcreteDecoratorB(); //往对象装饰A行为 d1.SetComponent(c); //继续装饰B行为 d2.SetComponent(d1); //执行 d2.Operation(); Console.Read(); }
运行结果
优势
装饰类和被装饰类可以独立发展,而不会相互耦合,不需要关系如何被太难见到对象链当中。它有效地把类的核心职责和装饰功能分开了
装饰模式是继承关系的一个替代方案
装饰模式可以动态地扩展一个实现类的功能
使用场景
当系统需要新功能的时候,是向旧的类中添加新的代码。这些新加的代码通常装饰了原有类的核心职责或主要行为
把每个要装饰的功能放在单独的雷总,并让这个类包含所要装饰的对象,在需要执行的时候,客户端代码可以在运行时根据需要有选择地按顺序地使用装饰功能包装对象
缺点
这种比继承更加灵活机动的特性,也同时意味着更加多的复杂性。
装饰模式会导致设计中出现许多小类,如果过度使用,会使程序变得很复杂。
装饰模式是针对抽象组件(Component)类型编程。但是,如果你要针对具体组件编程时,就应该重新思考你的应用架构,以及装饰者是否合适。当然也可以改变Component接口,增加新的公开的行为,实现“半透明”的装饰者模式。在实际项目中要做出最佳选择。