我也设计模式——13.Decorator
代码实现如下,注意几点:
1.Decorator中的Operation()方法是对被修饰对象ConcreteComponent中方法Operation()的封装
2.ConcreteDecorator中的Operation()方法是对其父类Operation()方法的封装,同时加入一些额外的新方法
3.ConcreteDecorator中的构造函数负责将修饰与被修饰对象链接在一起,如下图:
public interface Component
{
void Operation();
}
public class ConcreteComponent : Component
{
public void Operation()
{
Console.WriteLine("Old Function");
}
}
public class Decorator : Component
{
protected Component op;
public virtual void Operation()
{
op.Operation();
}
}
public class ConcreteDecoratorA : Decorator
{
public ConcreteDecoratorA(Component op)
{
this.op = op;
}
private void DoSomeThing1()
{
Console.WriteLine("New Function 1");
}
public override void Operation()
{
op.Operation();
DoSomeThing1();
}
}
public class ConcreteDecoratorB : Decorator
{
public ConcreteDecoratorB(Component op)
{
this.op = op;
}
private void DoSomeThing2()
{
Console.WriteLine("New Function 2");
}
public override void Operation()
{
base.Operation();
DoSomeThing2();
}
}
public class Client
{
public static void Main(string[] args)
{
ConcreteComponent c = new ConcreteComponent();
ConcreteDecoratorA d1 = new ConcreteDecoratorA(c);
ConcreteDecoratorB d2 = new ConcreteDecoratorB(d1);
d2.Operation();
}
}
{
void Operation();
}
public class ConcreteComponent : Component
{
public void Operation()
{
Console.WriteLine("Old Function");
}
}
public class Decorator : Component
{
protected Component op;
public virtual void Operation()
{
op.Operation();
}
}
public class ConcreteDecoratorA : Decorator
{
public ConcreteDecoratorA(Component op)
{
this.op = op;
}
private void DoSomeThing1()
{
Console.WriteLine("New Function 1");
}
public override void Operation()
{
op.Operation();
DoSomeThing1();
}
}
public class ConcreteDecoratorB : Decorator
{
public ConcreteDecoratorB(Component op)
{
this.op = op;
}
private void DoSomeThing2()
{
Console.WriteLine("New Function 2");
}
public override void Operation()
{
base.Operation();
DoSomeThing2();
}
}
public class Client
{
public static void Main(string[] args)
{
ConcreteComponent c = new ConcreteComponent();
ConcreteDecoratorA d1 = new ConcreteDecoratorA(c);
ConcreteDecoratorB d2 = new ConcreteDecoratorB(d1);
d2.Operation();
}
}
装饰者与被装饰者具有相同的接口,从而动态增加的功能不会破坏已有的接口,即修有一个对象后,其接口不发生变化
透明且动态的方式增加单个对象的功能
所谓透明,即用户仍可以直接访问被修饰者
另外一种增加功能的方法是继承
使用时保持被修饰者的功能单一,从而进行修饰的时候,可以组合出更多的功能,结构灵活——即被修饰者“原子化”
可以使用Decorator来给抽象工厂增加新方法,以为DB增加记录日志功能为例:
LogDB是这么写的:
public class LogDB : clsAbstractDB
{
private clsAbstractDB myDB;
public clsAbstractDB DB
{
get { return myDB; }
set { myDB = value; }
}
public override void Open()
{
myDB.Open();
Record("Open");
}
public override DataTable ExecSQL(string strSQL)
{
DataTable dt = myDB.ExecSQL(strSQL);
Record("ExecSQL: " + strSQL);
return dt;
}
//新方法 记录日志
private void Record(string strRecord)
{
//再次记录日志
}
}
{
private clsAbstractDB myDB;
public clsAbstractDB DB
{
get { return myDB; }
set { myDB = value; }
}
public override void Open()
{
myDB.Open();
Record("Open");
}
public override DataTable ExecSQL(string strSQL)
{
DataTable dt = myDB.ExecSQL(strSQL);
Record("ExecSQL: " + strSQL);
return dt;
}
//新方法 记录日志
private void Record(string strRecord)
{
//再次记录日志
}
}
经典的BufferStream:
由于在.NET中已经实现了框架,我们只看怎么使用:
Buffered的作用是为另一流上的读写操作添加一个缓冲层,从而提高读取和写入性能
public void BufferedStreamMethod(string path)
{
FileStream fs = File.Create(path);
Stream bs = new BufferedStream(fs);
AddText(bs, "Hello!");
}
public void AddText(Stream fs, string value)
{
byte[] info = new UTF8Encoding(true).GetBytes(value);
fs.Write(info, 0, info.Length);
}
{
FileStream fs = File.Create(path);
Stream bs = new BufferedStream(fs);
AddText(bs, "Hello!");
}
public void AddText(Stream fs, string value)
{
byte[] info = new UTF8Encoding(true).GetBytes(value);
fs.Write(info, 0, info.Length);
}
装饰模式与策略模式,两者能达到同样的效果——增加新功能,对比以下UML图,
二者的不同是,Decorator是从小到大,层层包装;Strategy是先制作大粒度对象,其中包括不变的对象和可变的部分。
微软的AJAX.NET控件是基于Decorator实现的,原来的TextBox等基本控件仍然可以使用,然而我们可以使用新的控件绑定到这个TextBox上,从而增加新的功能。