zoukankan      html  css  js  c++  java
  • 9 模板方法模式

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

    UML类图如下:

    TemplateMethod

    要点有两个:原语操作PrimitiveOperation以及钩子Hook()方法。

    代码举例

     1 public abstract class CaffeineBeverage
     2     {
     3         public void PrepareRecipe()
     4         {
     5             BoilWater();
     6             Brew();
     7             PourInCup();
     8             AddCondiments();
     9             TakeOut();
    10         }
    11         public void BoilWater()
    12         {
    13             Console.WriteLine("Boil Water");
    14         }
    15         public abstract void Brew();
    16         public void PourInCup()
    17         {
    18             Console.WriteLine("Pouring into Cup");
    19         }
    20         public abstract void AddCondiments();
    21         //打包
    22         public virtual void TakeOut(){}
    23     }
    24 
    25     class Coffee : CaffeineBeverage
    26     {
    27         public override void Brew()
    28         {
    29             Console.WriteLine("Brew Coffee Grinds");
    30         }
    31 
    32         public override void AddCondiments()
    33         {
    34             Console.WriteLine("Add Sugar and Milk");
    35         }
    36         public override void TakeOut()
    37         {
    38             Console.WriteLine("Will you take out? (y/n)");
    39             string yn = Console.ReadLine();
    40             if (yn == "y") Console.WriteLine("Take out");
    41         }
    42     }
    43 
    44     class Tea : CaffeineBeverage
    45     {
    46         public override void Brew()
    47         {
    48             Console.WriteLine("Steeping the Tea");
    49         }
    50 
    51         public override void AddCondiments()
    52         {
    53             Console.WriteLine("Adding Lemon");
    54         }
    55     }
    View Code

    这里Brew()与AddCondiments()便是两个原语操作,要在子类中重写。因为冲泡茶叶和咖啡都有类似的步骤,煮沸水BoilWater()->冲泡Brew()->倒入杯中PourInCup()->加辅料AddCondiments(),这种不变的步骤便是模板方法定义中所说的“算法步骤”,步骤或算法不能改变,所以PrepareRecipe()方法无法被重写,但在Brew()和AddCondiments()阶段,咖啡和茶叶的具体操作又有不同,比如AddCondiments(),咖啡可能加的是牛奶,而茶叶加的可能是柠檬,所以算法中这两个方法要被具体的子类实现,进行针对性的操作。

    另外,这儿还有个比较特殊的Hook钩子,钩子不是抽象方法,而是虚方法,它有自己的实现,但如果子类需要覆盖,也可以重写。这儿的例子中,用是否打包带走来举例,咖啡提供打包的服务,所以就重写了TakeOut()方法,但茶不允许外带,那么就留着父类中的TakeOut()空实现就好了。由此可见,钩子真是一个形象的名称。

    那么,在模板方法模式中,如果算法的一个步骤必须被子类亲自实现,则设置为原语操作(PrimitiveOperation),c#可把这种方法设置为abstract抽象方法;如果并不是强制子类重写的步骤,则用钩子,c#可用virtual虚方法实现。

    好莱坞原则

    别调用我们,我们会调用你。

    这个原则可以保证单向的依赖,避免出现高层组件与底层组件循环依赖的糟糕情况。

    遵循好莱坞原则,可以让底层组件挂钩到高层系统上,高层组件会决定什么时候和怎样使用它们。

    这和依赖倒置原则非常类似,但依赖倒置原则强调的是尽量避免使用具体类,而多使用抽象类;好莱坞原则更多是在教我们一个创建弹性设计的技巧,让底层组件能被挂钩进计算框架中,而且又不会让高层组件依赖低层组件。

    与策略模式、工厂方法的比较

    模板方法模式由子类决定如何实现算法中的步骤;策略模式封装可互换的行为,然后使用委托来决定要采用哪一个行为;工厂方法由子类决定实例化哪个具体类。

    模板方法模式用继承进行算法实现,策略模式用了组合的方式;策略模式可以在运行时改变算法,但模板方法模式无法做到这一点。

    最后,工厂方法是模板方法的一种特殊版本。

  • 相关阅读:
    Java 基础
    Mybatis
    Gateway
    Debug
    Nacos
    Debug
    Debug
    echars 折线图之一条线显示不同颜色,及拐点显示不同颜色
    捌月份生活随笔
    MyMatrix2022 64位版本下载 64bits Edition
  • 原文地址:https://www.cnblogs.com/zhixin9001/p/6081595.html
Copyright © 2011-2022 走看看