装饰器顾名思义就是对原有对象进行包装,在包装后的对象上调用行为。主要目的是让我们的设计符合单一职责尽可能的让一个类只包含一种职责,做到职责明确。符合这样的SOLID原则我们才能易于扩展使程序具有更好的扩展性。装饰器模式就是用来扩展已有类,被包装类和包装类首先都是实现同一接口。
以下面一个接口(IComponent)和两个类为例(Component和DecoratedComponent):
原理:Component实现了IComponent,DecoratedComponent用来作为扩展类。在DecoratedComponent的构造函数中接受一个IComponent类型参数,客户端调用时,用Component作为参数来实现接口。这样客户端既可以调用到原有类Component的行为方法,也可以调用到扩展类DecoratedComponent的行为方法。
IComponent:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace DecoratorPattern 8 { 9 internal interface IComponent 10 { 11 void DoSomething(); 12 } 13 }
Component:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace DecoratorPattern 8 { 9 internal class Component : IComponent 10 { 11 public void DoSomething() 12 { 13 Console.WriteLine("Do something in Component..."); 14 } 15 } 16 }
DecoratedComponent:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace DecoratorPattern 8 { 9 internal class DecoratedComponent : IComponent 10 { 11 private static IComponent _component; 12 13 public DecoratedComponent(IComponent component) 14 { 15 _component = component; 16 } 17 18 public void DoSomething() 19 { 20 DoSomethingElse(); 21 _component.DoSomething(); 22 } 23 24 public void DoSomethingElse() 25 { 26 Console.WriteLine("Do Something Else in DecoratedComponent..."); 27 } 28 } 29 }
//客户端调用
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace DecoratorPattern 8 { 9 internal class Program 10 { 11 private static IComponent component; 12 13 private static void Main(string[] args) 14 { 15 component = new DecoratedComponent(new Component()); 16 component.DoSomething(); 17 Console.ReadKey(); 18 } 19 } 20 }
之前也写过一篇关于代理模式的随笔,LZ觉得有异曲同工之处都是为了扩展行为,装饰器模式关注于在一个对象上动态的添加方法,然而代理模式关注于控制对对象的访问。换句话 说,用代理模式,代理类(proxy class)可以对它的客户隐藏一个对象的具体信息。因此,当使用代理模式的时候,我们常常在一个代理类中创建一个对象的实例。并且,当我们使用装饰器模 式的时候,我们通常的做法是将原始对象作为一个参数传给装饰者的构造器。