设计模式 学习笔记(3)装饰模式、代理模式
(6)装饰模式
装饰模式(Decorator),动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。《设计模式:可复用面向对象软件的基础》英文版《GOF》。
Component是定义一个对象接口,可以给这些对象动态地添加职责。ConcreteComponent是定义了一个具体的对象,也可以给这个对象添加一些职责。Decorator,装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,是无需知道Decorator的存在的。至于ConcreteDecorator就是具体的装饰对象,起到给Component添加职责的功能。下面来看一下基本的代码实现。
Component类
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
abstract class Component{ public abstract void Operation(); }
ConctreteComponent类
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class ConcretecComponent:Component { public override void Operation() { Console.WriteLine("具体对象的操作"); } }
Decorator类
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
abstract class Decorator:Component { protected Component component; public void SetComponent(Component component) { this.component=component; } public override void Operation() { if(component!=null) { component.Operation(); } } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
ConcreteDecoratotA类 class ConctreteDecoratorA:Decorator { private string addedState; //本类的独有功能,以区别于ConcreteDecoratorB public override void Operation() { base.Operation(); //首先运行原Component的Operation(),再执行本类的功能,如addedState,相当于对原Component进行了装饰 addState="new State"; Console.WriteLine("具体装饰对象A的操作"); } } class ConcteteDecoratorB:Decorator { public override void Operatopn() { base.Operation(); AddBehavior(); //首先运行原Component的Operation(),再执行本类的功能,如AddBehavior(),相当于对原Component进行了装饰 Console.WrieLine("具体在是对象B的操作") } private void AddedBahavior() //本类独有的方法,以区别与ConctreteDecoratorA { } }
客户端代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
static void Main(string[] args) { ConcreteComponent c=new ConcreteComponent(); ConcreteDecoratorA d1=new COncreteDecoratorA(); ConcreteDecoratorB d2=new ConcreteDecoratorB(); d1.SetComponent(c); d2.SetComponent(d1); d2.Operation(); //装饰的方法是:首先用ConcreteComponent实例化对象c,然后用ConcreteDecoratorA的实例化对象d1来实保证c,再用ConcreteDecoratorB的对象 //d2包装d1,最终在执行d2的Operation() Console.Read(); }
装饰模式是利用SetComponent来对对象进行包装。这样每个装饰对象的实现就和如何使用这个对象分离开了,即每个装饰对象只关心自己的功能,不需要关心如何被添加到对象链当中了。《设计模式解析第2版》
装饰模式是为已有功能动态地添加更多功能的一种方式。在起初的设计中,当系统需要新功能的时候,是向旧的类中添加新的代码。这些新加的代码通常装饰了原有类的核心职责或主要行为,在主类中加入新的字段和方法以及逻辑,增加了主类的复杂度,而往往这些新加入的东西仅仅是为了满足一些只在某种特定情况下才会执行的特殊行为的需要。而装饰模式却提供了一个非常好的解决方案,它把每个要装饰的功能放在单独的类中,并让这个类包装它所要装饰的对象,因为,当需要执行特殊行为时,客户代码就可以在运行时根据需要有选择地、按顺序地使用装饰功能包装对象了《DP》。
装饰模式的优点是,把类中的装饰功能从类中搬移去除,这样可以简化原有的类。这样做更大的好处就是有效地把类的核心职责和装饰功能区分开了。而且可以去除相关类中重复的装饰逻辑。
(7)代理模式
代理模式(Proxy),为其他对象提供一种代理以控制对这个对象的访问。
Subject类定义了RealSubject和Proxy的共用接口,这样就在任何使用RealSubject的地方都可以使用Proxy。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
abstract class Subject { public abstract void Request(); }
RealSubject类,定义Proxy所代表的真实实体。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
Proxy类,保存一个引用是的代理可以访问实体,并提供一个与Subject的接口相同的接口,这样代理就可以用来替代实体。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Proxy:Subject { RealSubject realSubject; public override void Request() { if(realSubject==null) { realSubject=new RealSubject(); } realSubject.Request(); } }
客户端代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
static void Main(string[] args) { Proxy proxy=new Proxy(); proxy.Request(); Console.Read(); }
代理模式其实就是在访问对象时引入一定程度的间接性,因为这种间接性,可以附加多种用途。代理就是真实对象的代表。