小看--模板方法设计模式

     模板方法设计模式:就是把两者的公共部分抽取出来当模板,把变化的部分当成扩展点丢出去。

  (一)知识点储备

    抽象类,抽象方法,虚方法,接口等,知识点理解,请看我的另外一篇博客:http://www.cnblogs.com/gdouzz/p/8387624.html

  (二)模板方法设计模式的演变

     下面模拟一个银行的客户端,有查询余额,计算利息,显示余额等功能,具体如下:

 /// <summary>
    /// 一个银行的客户端
    /// </summary>
    public class Client {
        /// <summary>
        /// 检查用户信息
        /// </summary>
        /// <param name="number"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        public bool CheckUser(int number, string password)
        {
            return DateTime.Now < DateTime.Now.AddDays(1);
        }

        public void Query(int number, string name, string password)
        {
            if (this.CheckUser(number, password))
            {
                double balance = this.QueryBalance(number);
                double interest = this.CaculateInterest(balance);
                this.Show(name,balance,interest);
            }
            else
            {
                Console.WriteLine("用户名和密码不正确");
            }
        }

        public double QueryBalance(int number)
        {
            return new Random().Next(10000,100000);
        }

        public double CaculateInterest(double balance)
        {
            return balance * 0.03;
        }

        /// <summary>
        /// 展示下
        /// </summary>
        /// <param name="name"></param>
        /// <param name="balance"></param>
        /// <param name="interest"></param>
        public void Show(string name, double balance, double interest) {
            Console.WriteLine("尊敬的{0}客户,你的账户余额为:{1},利息为{2}",
                name, balance, interest);
        }
    }

     假设上面这个是活期存款的,计算利息方法,现在来了个定期存款利息计算方法是0.05;其他的都不变,那么按照我们最简单的做法,那么就去计算利息的方法里面判断一下(if...else..)一下...然后随着银行的业务不断发展,理财业务也来了,除了利息不一样之外,在Show的时候,还应该给人做个提示:“投资有风险,理财需谨慎”;

     这个时候,模板方法设计模式,就出来了,根据我们上面的业务特点,我们需要给客户端抽取一个父类出来(这个父类,就是我们的模板,这个父类也是很有意思)。

  /// <summary>
    /// 银行客户端模拟
    /// </summary>
    public abstract class AbstractClient
    {
        /// <summary>
        /// 登陆查询功能
        /// </summary>
        /// <param name="id"></param>
        /// <param name="name"></param>
        /// <param name="password"></param>
        public void Query(int id, string name, string password)
        {
            if (this.CheckUser(id, password))
            {
                double balance = this.QueryBalance(id);
                double interest = this.CalculateInterest(balance);
                this.Show(name, balance, interest);
            }
            else
            {
                Console.WriteLine("账户密码错误");
            }
        }

        /// <summary>
        /// 用户检测
        /// </summary>
        /// <param name="id"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        public bool CheckUser(int id, string password)
        {
            return DateTime.Now < DateTime.Now.AddDays(1);
        }

        /// <summary>
        /// 查询余额
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public double QueryBalance(int id)
        {
            return new Random().Next(10000, 1000000);
        }

        /// <summary>
        /// 获取利率,计算利息
        /// 定期  0.05
        /// 活期  0.03
        /// 子类都有这个方法  但是各不相同   约束,所以这里采用了抽象方法。
        /// </summary>
        /// <param name="balance"></param>
        /// <returns></returns>
        public abstract double CalculateInterest(double balance);


        /// <summary>
        /// 这个展示的方法,定期查询类和活期查询类都一样,只是理财类不一致,所以采用了虚方法
        /// </summary>
        /// <param name="name"></param>
        /// <param name="balance"></param>
        /// <param name="interest"></param>
        public virtual void Show(string name, double balance, double interest)
        {
            Console.WriteLine("尊敬的{0}客户,你的账户余额为:{1},利息为{2}",
                name, balance, interest);
        }
    }

      之后的代码,就不贴出来了,模板方法设计模式是不是感觉特别简单,整个流程都是那么直白,不像访问者模式等等那么绕弯子。

    (三)题外话

      设计模式的来源是根据我们生活中常见的场景,每一个设计模式都是从场景出发的。模板方法设计模式,虽然简单,但是它的应用无处不在,只是我们平常可能都忽略罢了。就是一句话:把通用的东西封装起来,把变化的东西丢出去,就像平时我们自己做框架也是的,把通用的部分封装起来,留下扩展点。希望能给大家一点共鸣。

     

     

原文地址:https://www.cnblogs.com/gdouzz/p/8413585.html