模式探索(1):采用委托实现模版方法

 

2010-04-20 作者:conan 来源:conan的blog

 

由于看的人多,参与讨论的人少,我想可能是我写的过于简略了,所以今天重新编辑了一下。

模版方法的关键是在父类中的非抽象方法中调用抽象方法,子类各自实现自己父类的抽象方法。子类的区别仅仅是实现方法的不同,其自身原来的优势就是可以在有新的具体类的增加时不用修改抽象类,而客户端的调用则只是通过多态来执行抽象类的方法。在.NET中,我们可以采用委托方法实现相同的目的。

我们先来看看一般情况下如何实现模版方法:

using System;

namespace Basic
{
/**//// <summary>
///Class1 的摘要说明。
///</summary>
class Class1
{
/**////<summary>
///应用程序的主入口点。
///</summary>
[STAThread]
static void Main(string[] args)
{
AbstractClass Worker=new ConcreteClass1();
Console.WriteLine (Worker.TemplateMethod ());
Worker=new ConcreteClass2 ();
Console.WriteLine(Worker.TemplateMethod ());
Console.ReadLine ();
}
}
}


using System;

namespace Basic
{
/**////<summary>
///AbstractClass的摘要说明。
///</summary>
public abstract classAbstract Class
{
public AbstractClass()
{
//
//TODO:在此处添加构造函数逻辑
//
}

public string TemplateMethod()
{
string s="";
s+=Title();
s+=Body();
return s;
}
public abstrac tstring Title();
public abstract string Body();
}
}


using System;

namespace Basic
{
/**//// <summary>
/// ConcreteClass 的摘要说明。
/// </summary>
public class ConcreteClass1:AbstractClass
{
public ConcreteClass1()
{
//
//TODO:在此处添加构造函数逻辑
//
}
public override string Title()
{
return "标题1";
}
public override string Body()
{
return "内容1";
}
}
}


using System;

namespace Basic
{
/**//// <summary>
/// ConcreteClass 的摘要说明。
/// </summary>
public class ConcreteClass2:AbstractClass
{
public ConcreteClass2()
{
//
//TODO:在此处添加构造函数逻辑
//
}
public override string Title()
{
return "标题2";
}
public override string Body()
{
return "内容2";
}
}
}

结果显示:
标题1内容1
标题2内容2

再来看看用.net的委托来如何实现:

using System;

namespace TemplateMethod
{
/**//// <summary>
/// TemplateMethod的摘要说明。
///</summary>
public class TemplateMethod
{
public TemplateMethod()
{}
public delegate float Comp(float a,float b);
public Comp myComp;
public float DoComp(float[] f)
{
float nf=float.NaN;
foreach(float df in f)
{
if (float.IsNaN(nf))
{
nf=df;
}
else
{
nf=myComp(nf,df);
}}return nf;
}
}
}

在DoComp类中我们定义与上面的委托相同的方法,这个类与TemplateMethod无关,只是其中方法的参数签名和返回值与上面的代理相同。如此,比较原来的实现方法,是不是少了上面那个继承的环节,实际上消除了原来的泛化关系,自然实现了抽象类和具体类的退藕(虽然此时已看不到任何泛化关系)。所以,我认为只要利用好.NET中的委托(.NET独有的特性)和反射可以大大加强软件的抽象和面向对象性,各位如果从前有比较好的面向对象基础,想必好好研究委托和反射对你的.NET学习将大有俾益:

using System;

namespace TemplateMethod
{
/**////<summary>
///DoComp的摘要说明。
///</summary>
public class DoComp
{
public DoComp()
{
}
public float c1(float a,float b)
{
return a+b;
}
public float c2(float a,float b)
{
return a*b;
}
}
}


好处就是使用时可以动态组装(我认为):

using System;

namespace TemplateMethod
{
/**////<summary>
///Class1的摘要说明。
///</summary>
class Class1
{
/**//// <summary>
/// 应用程序的主入口点。
///</summary>
[STAThread]
static void Main(string[] args)
{
TemplateMethod tm=new TemplateMethod ();
float[] f={1,2,3,4};
DoComp c=new DoComp ();
tm.myComp +=new TemplateMethod.Comp(c.c1);
System.Console .WriteLine(tm.DoComp(f).ToString());
tm.myComp -=new TemplateMethod.Comp(c.c1);
tm.myComp +=new TemplateMethod .Comp (c.c2);
System.Console.WriteLine(tm.DoComp(f).ToString());
System.Console.ReadLine();
}
}
}

结果显示:
10
24

这种方法可以说是模版方法的变相使用,但无疑达到了退藕的作用。但它比原来的方法也有它的缺点,就是如果在方法中涉及到对象的状态,这种方法则不太好用了,因为状态需要继承关系去维护,我们在此消灭了继承自然无法维护状态。
另:大家如果对下面的代码输出结果的
10
24
有任何疑惑的地方,建议下载代码后设断点调试一下,那样对整个过程会有比较清晰的了解。




如何向妻子解释OOD
OOAD与UML笔记
UML类图与类的关系详解
UML统一建模语言初学
总结一下领域模型的验证
基于 UML 的业务建模


面向对象的分析设计
基于UML的面向对象分析设计
UML + 嵌入式系统分析设计
关系数据库面向OOAD设计
业务建模与业务架构
使用用例进行需求管理


某航空IT部门 业务分析与业务建模
联想 业务需求分析与建模
北京航管科技 EA工具与架构设计
使用EA和UML进行嵌入式系统分析
全球最大的茶业集团 UML系统分析
华为 基于EA的嵌入式系统建模
水资源服务商 基于EA进行UML建模
更多...   
 
 
 
 
 

组织简介 | 联系我们 |   Copyright 2002 ®  UML软件工程组织 京ICP备10020922号

京公海网安备110108001071号