NET框架中的 Decorator 和 Strategy 模式
NET框架中的 Decorator 和 Strategy 模式
应用场景:net 框架下的TextWriter,HtmlTextWriter,CssTextWriter,IndentedTextWriter 等
先看一下Decorator 模式结构图:
NET 下的 Decorator 模式(TextWriter及其派生类):
虽然图形有所不同,但大致结构相似。
这里就大概先分析一下吧。
TextWriter 作为 一个抽象类定义形式如下:
public abstract class TextWriter : MarshalByRefObject, IDisposable
{
.....
public virtual Write(...);
.....
public virtual WriteLine(...);
.....
}
里面的Write及WriteLine函数全部是虚方法,因此可以在子类中被重写, 我们一会能看到子类中的这些方法会在调用基类方法之前
进行一些其它的操作:)
派生类(以HtmlTextWriter 为例)声明如下:
public class HtmlTextWriter : TextWriter
{
.....
public virtual Write(...);
.....
public virtual WriteLine(...);
.....
}
这里用其中的Write(bool value)函数说明如下:
public override void Write(bool value)
{
if (this.tabsPending) --->先进行“添加职责”操作
{
this.OutputTabs();
}
this.writer.Write(value); --->最后调用基类方法
}
这里就是这种模式所说的"在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。"
备注:1 .CssTextWriter, SyncTextWriter 类只是将TextWriter作为构造参数传入,未进行"添加职责"的处理,同时
这两个类的声明如下:
internal sealed class CssTextWriter : TextWriter
internal sealed class SyncTextWriter : TextWriter, IDisposable
2. IndentedTextWriter 类与HtmlTextWriter在Write函数中大同小异, 代码如下:
public override void Write(bool value)
{
this.OutputTabs();
this.writer.Write(value);
}
3. StreamWriter,StringWriter 的实现与其它的Writer类有差异,可参考的使用方法如下:
IndentedTextWriter tw = new IndentedTextWriter(new StreamWriter(_strFileName, false), "");
......
HtmlTextWriter htw = new IndentedTextWriter(new StreamWriter(memoryStream, Encoding.GetEncoding("GB18030")));
......
HtmlTextWriter writer=new HtmlTextWriter(new System.IO.StringWriter());
......
总体上说,Decorator 结构还是很清楚的,也很好理解。这里再把这种模式的意图和适用性拷贝如下,以加深理解:
意图: 动态地给一个对象添加一些额外的职责。就增加功能来说,比生成子类更为灵活。
适用性: 1. 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
2. 处理那些可以撤消的职责。
3. 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产
生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于
生成子类。
相关参考: http://topic.csdn.net/t/20040325/09/2883578.html
http://hi.baidu.com/xiao0856/blog/item/e96479d0855fb18ea0ec9cc5.html
下面,接着再说一下这个架构下的另一个模式 Strategy
还是先看一下Strategy 模式的结构图:
NET 下的 Strategy 模式(Stream及其派生类):
相信大家已看清楚了,基本上调用的流程如下:
StreamWriter 对象实例--->Write--->Flush(bool flushStream, bool flushEncoder)
Flush函数的实现如下:
private void Flush(bool flushStream, bool flushEncoder)
{
if (this.stream == null)
{
__Error.WriterClosed();
}
if (((this.charPos != 0) || flushStream) || flushEncoder)
{
if (!this.haveWrittenPreamble)
{
this.haveWrittenPreamble = true;
byte[] preamble = this.encoding.GetPreamble();
if (preamble.Length > 0)
{
this.stream.Write(preamble, 0, preamble.Length); //调用指定的STREAM对象的write函数
}
}
int count = this.encoder.GetBytes(this.charBuffer, 0, this.charPos, this.byteBuffer, 0, flushEncoder);
this.charPos = 0;
if (count > 0)
{
this.stream.Write(this.byteBuffer, 0, count); //调用指定的STREAM对象的write函数
}
if (flushStream)
{
this.stream.Flush();
}
}
}
到这里大家就该明白了吧:)
调用的方式可以是这样(以FileStream为例):
FileStream fs = new FileStream(Server.MapPath(".")+"\\test.txt",FileMode.Create,FileAccess.Write);
StreamWriter sw = new StreamWriter(fs);
sw.WriteLine("这里是内容");
......
sw.Close();
fs.Close();
这里再把这种模式的意图和适用性拷贝如下,以加深理解:
意图: 定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
适用性: 1. 许多相关的类仅仅是行为有异。“策略”提供了一种用多个行为中的一个行为来配置一个类的方法。
2. 需要使用一个算法的不同变体。例如,你可能会定义一些反映不同的空间/时间权衡的算法。当这些变体实现为一个算法的类层次时[ H O 8 7 ] ,可以使用策略模式。
3. 算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构。
4. 一个类定义了多种行为, 并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入它们各自的S t r a t e g y 类中以代替这些条件语句。
推广:其实将上面的类图中的StreamWriter 换成 StreamReader, 也是这个模式,只不过这两个类在.net 共存而已。
这里把这两个模式一起抬出来只是因为在分析类似Writer,Reader类时同时发现的,为了体现整个性才一起搬出来:)
因为这篇文章的内容只是学习.net框架时的“副产品”,因此里面的内容可读性不强,同时肯定会有偏颇之
处。如果大家有不同意见,希望回复本人,以纠正本人的误解,希望不要误导大家:)