快精灵印艺坊 您身边的文印专家
广州名片 深圳名片 会员卡 贵宾卡 印刷 设计教程
产品展示 在线订购 会员中心 产品模板 设计指南 在线编辑
 首页 名片设计   CorelDRAW   Illustrator   AuotoCAD   Painter   其他软件   Photoshop   Fireworks   Flash  

 » 彩色名片
 » PVC卡
 » 彩色磁性卡
 » 彩页/画册
 » 个性印务
 » 彩色不干胶
 » 明信片
   » 明信片
   » 彩色书签
   » 门挂
 » 其他产品与服务
   » 创业锦囊
   » 办公用品
     » 信封、信纸
     » 便签纸、斜面纸砖
     » 无碳复印纸
   » 海报
   » 大篇幅印刷
     » KT板
     » 海报
     » 横幅

一次重构导向设计模式的实践(.NET)

代码仅仅是说明问题,和实际的有所不同
在项目开发过程中,有这样的需求:定义一个查询窗体使用DataGrid显示列表
双击Grid后打开指定记录的编辑页面,窗体类为FormSearchEntity于是这么写了
private void Grid_DoubleClick(object sender,System.EventArgs e)
{
string entityID = 双击记录的ID字段值; //这个有固定的办法
FormEntity frmEntity = new FormEntity(entityID);
........
frmEntity.Show();
}
其中的FormEntity就是对业务实体的编辑界面,在构造函数中传入一个ID,然后
加载该记录的相关数据,在这里不作重点解释。

接下来有要在查询界面上添加一个按钮“Go”,执行的动作和Grid双击是相同的,就是
在Grid中选中记录,点击Go打开实体的操作界面。

这样,就使用重构中的Extract Method手法:
private void Grid_DoubleClick(object sender,System.EventArgs e)
{
string entityID = 双击记录的ID字段值;
OpenEntityForm(entityID);

}
private void btnGo_Click(object sender,System.EventArgs e )
{
string entityID = 双击记录的ID字段值;
OpenEntityForm(entityID);
}
private void OpenEntityForm(string entityID)
{
FormEntity frmEntity = new FormEntity(entityID);
........
frmEntity.Show();
}

到现在看来,这样作有什么用呢?直接在Go的Click时间中调用Grid的DoubleClick不就行了吗?事实上Extract Method不仅仅是防止重复代码
同时也可以提高代码的可重用性,作用在下面会看到。

现在,又要对另一个的表进行同样的操作,那就再定义一个窗体,把上面的代码改改就成了,但是就出现了重复代码,这是不好的味道。那么这样作:把OpenEntityForm方式改为Virtual,同时声明为Protected,里面的代码都去掉
protected void OpenEntityForm(string entityID)
{

}
把窗体更名为FormSearchEntityBase再重新写一个类FormSearchEntityA来继续FormSearchEntityBase,override父类的OpenEntityForm方式

protected override void OpenEntityForm(string entityID)
{
FormEntityA frmEntityA = new FormEntityA(entityID);
........
frmEntityA.Show();
}

实体B的查询界面也相同FormSearchEntityB继续自FormSearchEntityBase,override父类的OpenEntityForm方式
protected override void OpenEntityForm(string entityID)
{
FormEntityB frmEntityB = new FormEntityB(entityID);
........
frmEntityB.Show();
}
这样,假如后面还有一样的需求,就从FormSearchEntityBase继续一个类,override父类的OpenEntityForm方式就可以了

现在,来看看TemplateMethod模式
意图:
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。
适用性:
一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。
各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复
控制子类扩展

例子代码:
namespace TemplateMethod_DesignPattern
{
using System;

class Algorithm
{
public void DoAlgorithm()
{
Console.WriteLine("In DoAlgorithm");

// do some part of the algorithm here

// step1 goes here
Console.WriteLine("In Algorithm - DoAlgoStep1");
// . . .

// step 2 goes here
Console.WriteLine("In Algorithm - DoAlgoStep2");
// . . .

// Now call configurable/replacable part
DoAlgoStep3();

// step 4 goes here
Console.WriteLine("In Algorithm - DoAlgoStep4");
// . . .

// Now call next configurable part
DoAlgoStep5();
}

virtual public void DoAlgoStep3()
{
Console.WriteLine("In Algorithm - DoAlgoStep3");
}

virtual public void DoAlgoStep5()
{
Console.WriteLine("In Algorithm - DoAlgoStep5");
}
}

class CustomAlgorithm : Algorithm
{
public override void DoAlgoStep3()
{
Console.WriteLine("In CustomAlgorithm - DoAlgoStep3");
}

public override void DoAlgoStep5()
{
Console.WriteLine("In CustomAlgorithm - DoAlgoStep5");
}
}

/// <summary>
/// Summary description for Client.
/// </summary>
public class Client
{
public static int Main(string[] args)
{
CustomAlgorithm c = new CustomAlgorithm();

c.DoAlgorithm();

return 0;
}
}
}


再来对比下上面对窗体类进行改动的代码和TemplateMethod的例子代码,这就是一个TemplateMethod模式了

有一种观点说在设计期使用设计模式常会导致过渡设计,目前的灵敏方式和重构都徐徐提倡代码演化和重构达到设计模式。
我也是在写完代码后才发现这已经是一个模式了。






返回类别: 教程
上一教程: .net下软件的自动升级--上传
下一教程: 前言[《.net框架程序设计》读书笔记]

您可以阅读与"一次重构导向设计模式的实践(.NET)"相关的教程:
· ASP.NET下MVC设计模式的实现
· Prototype设计模式的实现
· .NET中的设计模式五:观察者模式
· .NET中的设计模式二:单件模式
· ASP.NET可交互式位图窗体设计(9)
    微笑服务 优质保证 索取样品