定义:动态的给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
结构图:
Component类:
/// <summary> /// 定义的一个对象接口(抽象类) /// 可以给这些对象动态的添加职责 /// </summary> public abstract class Component { public abstract void Operation(); }
ConcreteComponent类:
/// <summary> /// 一个具体的对象,可以为该对象添加一些职责 /// </summary> public class ConcreteComponent : Component { public override void Operation() { Console.WriteLine("具体对象操作"); } }
Decorator类:
/// <summary> /// 装饰抽象类 /// 继承了Component,从外类来扩展Component类的功能, /// 但对于Component来说,是无需知道Decorator的存在 /// </summary> public class Decorator : Component { protected Component component; public void SetComponent(Component component) { this.component = component; } /// <summary> /// 重写Operation(),实际执行的是Component的Operation() /// </summary> public override void Operation() { if (component != null) { component.Operation(); } } }
ConcreteDecoratorA类:
/// <summary> /// 具体装饰对象A /// </summary> public class ConcreteDecoraterA : Decorator { private string addedState; public override void Operation() { base.Operation(); addedState = "New State"; Console.WriteLine("具体装饰对象A的操作"); } }
ConcreteDecoratorB类:
/// <summary> /// 具体装饰对象B /// </summary> public class ConcreteDecoratorB : Decorator { public override void Operation() { base.Operation(); AddedBehavior(); Console.WriteLine("具体装饰对象B的操作"); } private void AddedBehavior() { } }
客户端代码:
class Program { static void Main(string[] args) { ConcreteComponent c = new ConcreteComponent(); ConcreteDecoraterA d1 = new ConcreteDecoraterA(); ConcreteDecoratorB d2 = new ConcreteDecoratorB(); /*装饰方法是:首相用ConcreteComponent实例化对象c 然后用ConcreteComponentA的实例化对象d1来包装c 再用ConcreteComponentB的实例化对象d2来包装d1 最后执行d2的Operation() */ d1.SetComponent(c); d2.SetComponent(d1); d2.Operation(); Console.Read(); } }
装饰模式和代理模式比较:
装饰模式:关注于在一个对象上动态的添加方法。
代理模式:关注于控制对象的访问。
装饰模式和扩展方法比较:
装饰模式解决的主要问题是:避免为类型增加成员而过多的派生子类。那么除了使用装饰模式,是否还有其他方法解决这个问题呢?
答案当然是肯定的,我们可以通过扩展方法的方式来实现,
那么问题来了,装饰模式和扩展方法有何区别呢?
不同点:
1.装饰模式是对源对象进一步的封装,实际使用的是装饰后的对象;而扩展方法只是动态的增加方法,实际使用的还是源对象。
2.装饰后的对象中的新方法如何和源对象方法相同,会覆盖掉源对象的方法;扩展方法如何和实例方法名称相同,则扩展方法不会被调用。
3.装饰模式除了可以为源对象增加成员方法之外,还可以增加属性;而扩展方法只能动态的增加方法。
相同点:
1.都不用修改源对象
关于扩展方法的详细描述可参考: