23种设计模式 第三部分 关系模式(2)模板方法模式

原创 2016年08月28日 20:50:32


理解

模板方法定义了一个算法的步骤,并允许子类为一个或多个步骤提供实现。

泡茶和泡咖啡,步骤很相似:


两种饮品其分别的做法如下代码:

public class Coffee 
{ 
    public void PrepareRecipe() 
    { 
        //烧水 
        BoilWater(); 
        //冲咖啡 
        BrewCoffeeGrinds(); 
        //倒入茶杯中 
        PourInCup(); 
        //加入糖和咖啡 
        AddSugarAndMilk(); 
    } 
    public void BoilWater() 
    { 
        Console.WriteLine("烧水"); 
    }

    public void BrewCoffeeGrinds() 
    { 
        Console.WriteLine("冲咖啡"); 
    }

    public void PourInCup() 
    { 
        Console.WriteLine("倒入杯子中"); 
    }

    public void AddSugarAndMilk() 
    { 
        Console.WriteLine("加糖和牛奶"); 
    } 
}

public class Tea 
{ 
    public void PrepareRecipe() 
    { 
        //烧水 
        BoilWater(); 
        //泡茶 
        SteepTeaBag(); 
        //倒入茶杯中 
        PourInCup(); 
        //加入柠檬 
        AddLemon(); 
    } 
    public void BoilWater() 
    { 
        Console.WriteLine("烧水"); 
    }

    public void SteepTeaBag() 
    { 
        Console.WriteLine("泡茶"); 
    }

    public void PourInCup() 
    { 
        Console.WriteLine("倒入杯子中"); 
    }

    public void AddLemon() 
    { 
        Console.WriteLine("加柠檬"); 
    } 
}
烧水和带入杯子的方法显然是重复的,这样就不符合代码复用。 
对比两种做法,都是需要四个步骤,把相同的使用一个基类,不同的部分分别由自己的子类去实现。

冲咖啡和泡茶以及加入咖啡和牛奶都是属于差不多动作相同的。所以可以继续抽象,抽象为“泡”和“加调料”。抽象后的方法大致如此:




得出的也就是我们的模板方法。下面来看看模板方法模式的类图:


实现

public abstract class CoffeeinBeverage1
{
    public  void BoilWater()
    {
        Console.WriteLine("烧水");
    }

    public  void PrepareRecipe()
    {
        BoilWater();
        Brew();
        PourInCup();
        AddCondiments();
    }

    public  void PourInCup()
    {
        Console.WriteLine("倒入杯子中");
    }

    public abstract void Brew();

    public abstract void AddCondiments();

}
咖啡:

public class Coffee1 : CoffeeinBeverage1
{
    public override void Brew()
    {
        Console.WriteLine("冲咖啡");
        
    }

    public override void AddCondiments()
    {
        Console.WriteLine("加糖和牛奶");
    }
茶:

public class Tea1 : CoffeeinBeverage1
{
    public override void Brew()
    {
        Console.WriteLine("泡茶");
    }

    public override void AddCondiments()
    {
        Console.WriteLine("加柠檬");
    }

}

分析

模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法似的自雷可以在不改变算法结构的情况下,重新定义算法中的某些步骤。

这个模式用来创建一个算法的模板。什么是模板?如你所见,模板就是一个方法。更具体的说,这个方法将算法定义成一组步骤,其中的任何步骤都可以是抽象的,由子类负责实现。这可以确保算法的结构保持不变,同时由子类提供部分实现。

模板方法挂钩(使用钩子)

在上面的茶水和咖啡中,现在是看起来能喝了,但是有个问题就是有些人喝咖啡喜欢不加任何调味料的。那么我们硬是给客人加,肯定是会生气的。为了满足这个要求,设计模式提供的有这个解决方案——使用钩子。具体什么是钩子,我们小的时间的课本上有个猴子捞月亮的图片:


钩子是一种被声明在抽象类中的方法,但只有空的或者默认的实现。钩子可以让子类幼儿管理对算法的不同点进行挂钩(子类决定是否覆盖抽象类中的方法)。

public  void PrepareRecipe()
    {
        BoilWater();
        Brew();
        PourInCup();
        //有个判断方法来添加调料
        if (WantCondiments())
        {
            AddCondiments();
        }
    }
    /// <summary>
    /// 加入一个方法,用来判断是否需要加调料
    /// </summary>
    /// <returns></returns>
    public virtual bool WantCondiments()
    {
        return true;
    }


在子类中,可以通过不同的方式类覆盖WantCondiment()方法。用来表示是否要加调料的标准,在此方法中注意必须加入virtual关键字,以便子类中使用override重写。下面看看咖啡中的方法:

public override bool WantCondiments()
   {
       return false;
   }

咖啡:

class Program
  {
      static void Main(string[] args)
      {
          CoffeeinBeverage1 coffeninBeverage = new Coffee1();
          coffeninBeverage.PrepareRecipe();
          Console.ReadKey();
      }
  }

输出:


已经去掉了调料。

模板方法模式还涉及到一个好莱坞原则:

别调用(打电话给)我们,我们会调用(打电话给)你。

在模板方法模式中扮演好莱坞的角色是抽象类,子类是演员的角色。

我们允许低层组件将自己挂钩到系统上,但是高层组件会决定什么时候和怎样使用这些低层组件。换句话说,高层组件对待低层组件的方式是“别调用我们,我们会调用你。”我们要做的事,避免让高层和低层组件之间有明显的环状依赖。

总结

对比模板方法模式、策略模式以及工厂方法模式:

模板方法  - -> 封装可互换的行为,然后使用委托来决定要采用哪一个行为。

策略   -- >子类决定如何实现算法中的步骤。

工厂方法  -- > 由子类决定实例化哪个具体类。



版权声明:本文为博主原创文章,未经博主允许不得转载。

23种设计模式汇总整理

设计模式分为三大类:创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。行为型...
  • jason0539
  • jason0539
  • 2015年04月09日 10:57
  • 74443

23种设计模式(13):适配器模式

本文主要介绍设计模式中的适配器模式。
  • psp0001060
  • psp0001060
  • 2016年02月25日 16:21
  • 674

23 种设计模式 记忆技巧

记忆口决:抽工建原单代桥组装享适门观模策状备迭访中命解职第一行为创建型模式。第二行为结构型模式。第三行为行为模式。   想象如下的场景:大家都在抽出工夫来建造原单。原单的内容是代桥来组装享适门。大家都...
  • liyongjin2009
  • liyongjin2009
  • 2011年05月26日 18:32
  • 746

23种设计模式概要及易懂的例子

23种设计模式(分为三大类)   因为内容是从有道云笔记挪过来的,所以排版有点丑,如有不足或错误还望指点。。 注意,一些设计模式之间的(代码)"形式"虽然相同或相似,但是"语义"是截然不同的...
  • ycl295644
  • ycl295644
  • 2015年08月20日 09:04
  • 3467

23种设计模式及java实现

一、设计模式的分类 总体来说设计模式分为三大类: 创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。 结构型模式,共七种:适配器模式、装饰器模式、代理模...
  • zmx729618
  • zmx729618
  • 2016年05月27日 14:02
  • 2090

[设计模式]二十三种设计模式

分类: DesignPattern(8)  目录(?)[+] 原文地址:http://blog.csdn.net/zhangerqing 一、设计模...
  • qq3965470
  • qq3965470
  • 2016年08月09日 23:54
  • 4987

23种设计模式全解析-- 设计模式看这一篇就够了

二、设计模式的六大原则 总原则:开闭原则(Open Close Principle) 开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,而是要扩展原有代码,实现一...
  • AlbertFly
  • AlbertFly
  • 2016年08月22日 11:34
  • 3411

23种常用设计模式(C++)

23种常用设计模式(C++)
  • u012212811
  • u012212811
  • 2014年11月05日 06:17
  • 2428

设计模式的意义与23种常见模式介绍

自从计算机诞生以来,生产效率大大的提高,尤其是微型计算机能够进入千家万户。让大众能够利用强大的计算资源,但是单纯的计算机硬件虽然能够提供机械强大的计算能力,但是要有效的利用这样的能力就需要用软件去操作...
  • micro_hz
  • micro_hz
  • 2016年12月03日 16:08
  • 1015

GOF23种设计模式精解

创建型 1. Factory Method(工厂方法) 2. Abstract Factory(抽象工厂) 3. Builder(建造者) 4. Prototype(原型) 5. Singleton(...
  • zhangcanyan
  • zhangcanyan
  • 2016年06月28日 21:14
  • 7727
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:23种设计模式 第三部分 关系模式(2)模板方法模式
举报原因:
原因补充:

(最多只允许输入30个字)