苏飞论坛

 找回密码
 马上注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

分布式系统框架(V2.0) 轻松承载百亿数据,千万流量!讨论专区 - 源码下载 - 官方教程

HttpHelper万能框架(V2.3-含.netcore) HttpHelper官方出品,无敌框架讨论区 - 源码下载 - 在线测试和代码生成

HttpHelper爬虫类(V2.0) 最牛的爬虫类,没有爬不到只有想不到 源码 - 代码生成器 - 讨论区 - 教程- 例子

查看: 805|回复: 6

[学习心得] C#模板模式例子

[复制链接]
发表于 2019-1-15 15:25:35 | 显示全部楼层 |阅读模式
一 、  一个实际应用模板方法的例子

下面的例子演示了数据库访问的模板方法。实际应用时,请确保 C 盘根目录下有 nwind.mdb 这个 Access 数
据库(可以从 Office 的安装目录下找到。中文版用户的请注意字段名可能有所不同)。

[C#] 纯文本查看 复制代码
using System;
using System.Data;
using System.Data.OleDb;

namespace ConsoleApplication1
{
    // "AbstractClass"
    abstract class DataObject
    {
        // Methods
        public abstract void Connect();
        public abstract void Select();
        public abstract void Process();
        public abstract void Disconnect();
        // The "Template Method"
        public void Run()
        {
            Connect();
            Select();
            Process();
            Disconnect();
        }
    }
    // "ConcreteClass"
    class CustomerDataObject : DataObject
    {
        private string connectionString =
            "provider=Microsoft.JET.OLEDB.4.0; "
            + "data source=c:\\nwind.mdb";
        private string _commandString;
        private DataSet _dataSet;
        // Methods
        public override void Connect()
        {
            // Nothing to do
        }
        public override void Select()
        {
            _commandString = "select CompanyName from Customers";
            OleDbDataAdapter dataAdapter = new OleDbDataAdapter(
                _commandString, connectionString);
            _dataSet = new DataSet();
            dataAdapter.Fill(_dataSet, "Customers");
        }
        public override void Process()
        {
            DataTable dataTable = _dataSet.Tables["Customers"];
            foreach (DataRow dataRow in dataTable.Rows)
                Console.WriteLine(dataRow["CompanyName"]);
        }
        public override void Disconnect()
        {
            // Nothing to do
        }
    }
    /// <summary>
    /// TemplateMethodApp test
    /// </summary>
    public class TemplateMethodApp
    {
        public static void Main(string[] args)
        {
            CustomerDataObject c = new CustomerDataObject();
            c.Run();
        }
    }
}


二 、  模版方法模式中的方法

模版方法中的方法可以分为两大类:模版方法(Template Method)和基本方法(Primitive Method)。

模版方法

一个模版方法是定义在抽象类中的,把基本操作方法组合在一起形成一个总算法或一个总行为的方法。这个模版
方法一般会在抽象类中定义,并由子类不加以修改地完全继承下来。

基本方法

基本方法又可以分为三种:抽象方法(Abstract Method)、具体方法(Concrete Method)和钩子方法(HookMethod)。
抽象方法一个抽象方法由抽象类声明,由具体子类实现。在 C#语言里一个抽象方法以 abstract 关键字标示出来。

具体方法:一个具体方法由抽象类声明并实现,而子类并不实现或置换。在 C#语言里面,一个具体方法没有
abstract 关键字。

钩子方法:一个钩子方法由抽象类声明并实现,而子类会加以扩展。通常抽象类给出的实现是一个空实现,作为
方法的默认实现。(Visual FoxPro 中项目向导建立的项目会使用一个 AppHook 类实现监视项目成员变化,调
整系统结构的工作。)钩子方法的名字通常以 do 开始。


三 、  重构的原则

在对一个继承的等级结构做重构时,一个应当遵从的原则便是将行为尽量移动到结构的高端,而将状态尽量移动
到结构的低端。

1995 年,Auer 曾在文献【AUER95】中指出:

1. 应当根据行为而不是状态定义一个类。也就是说,一个类的实现首先建立在行为的基础之上,而不是建立在状态的基础之上。

2. 在实现行为时,是用抽象状态而不是用具体状态。如果一个行为涉及到对象的状态时,使用间接的引用而不是直接的引用。换言之,应当使用取值
方法而不是直接引用属性。

3. 给操作划分层次。一个类的行为应当放到一个小组核心方法(KernelMethods)里面,这些方法可以很方便地在子类中加以置换。

4. 将状态属性的确认推迟到子类中。不要在抽象类中过早地声明属性变量,应将它们尽量地推迟到子类中去声明。在抽象超类中,如果需要状态属性
的话,可以调用抽象的取值方法,而将抽象的取值方法的实现放到具体子类中。

如果能够遵从这样的原则,那么就可以在等级结构中将接口与实现分隔开来,将抽象与具体分割开来,从而保证
代码可以最大限度地被复用。这个过程实际上是将设计师引导到模版方法模式上去。
发表于 2019-1-15 15:33:50 | 显示全部楼层
发表于 2019-1-15 15:38:21 | 显示全部楼层
发表于 2019-1-15 16:48:58 | 显示全部楼层
发表于 2019-1-15 17:08:10 | 显示全部楼层
发表于 2019-1-15 22:41:04 | 显示全部楼层
发表于 2019-1-16 15:34:40 | 显示全部楼层
您需要登录后才可以回帖 登录 | 马上注册

本版积分规则

QQ|手机版|小黑屋|手机版|联系我们|关于我们|广告合作|苏飞论坛 ( 豫ICP备17001017号-1)

GMT+8, 2019-12-7 23:06

© 2017-2018

快速回复 返回顶部 返回列表