• C#设计模式之9:模板方法


    模板方法

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

    本例中用冲泡咖啡和茶的例子来说明:

    上图说明了冲泡咖啡和茶的步骤,可以看出冲泡咖啡和茶的步骤差不多,很相似,先来看看没有应用模板方法的代码:

    Tea的代码类似,就不放了。他们的一个不好的地方在于算法散落在了各个类中,还有一点是重复的代码。

    public abstract class CaffeineBeverage//设计一个抽象类,将算法进行封装
        {
            public void BoilWater()
            {
                Console.WriteLine("boil water");
            }
    
            public void PourInCup()
            {
                Console.WriteLine("pour in cup");
            }
    
            public void PrepareRecipe()//封装算法,这个就是模板方法。
            {
                BoilWater();
                Brew();
                PourInCup();
                AddCondiment();
            }
            public abstract void Brew();//具体的实现要到子类中实现
            public abstract void AddCondiment();//具体的实现要到子类中实现
        }
        public class TeaLogic: CaffeineBeverage
        {
            public override void Brew()
            {
                Console.WriteLine("brew tea");
            }
    
            public override void AddCondiment()
            {
                Console.WriteLine("add some lemon");
            }
        }
        public class CoffeLogin:CaffeineBeverage
        {
            public override void Brew()
            {
                Console.WriteLine("brew coffe...");
            }
    
            public override void AddCondiment()
            {
                Console.WriteLine("add some milk and sugar...");
            }
        }

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

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

    同时,AbstractClass内部定义一个钩子方法——一个虚方法,可以在子类中决定是否重写,达到挂钩的目的。钩子的存在,可以让子类有能力对算法的不同点进行挂钩,要不要挂钩,由子类自行决定。

    //在模板方法中应用钩子
        public abstract class AnotherKindOfCoffeineBeverage
        {
            public void BoilWater()
            {
                Console.WriteLine("boil water");
            }
            public void PourInCup()
            {
                Console.WriteLine("pour in cup..");
            }
            public virtual bool CustomerWantCondiment()//虚方法。。表示一个钩子
            {
                return true;
            }
            public abstract void Brew();
            public abstract void AddCondiment();
            public void PrepareRecipe()
            {
                BoilWater();
                Brew();
                if (CustomerWantCondiment())
                {
                    AddCondiment();
                }
                PourInCup();
            }
        }
        //应用钩子方法的一个场景
        public class AnotherKindOfTea : AnotherKindOfCoffeineBeverage
        {
            public override bool CustomerWantCondiment()
            {
                return GetCustomerInput().Equals("y");
            }
            public override void Brew()
            {
                Console.WriteLine("dropping coffe through filter..");
            }
            public override void AddCondiment()
            {
                Console.WriteLine("add some condiment..");
            }
            private string GetCustomerInput()
            {
                Console.WriteLine("would you like some lemon with your tea?(y/n)");
                var input = Console.ReadLine();
                return input?.ToLower();
            }
        }

    关于钩子,由这么一个原则:当你必须提供模板方法中的某个步骤时,就在基类中做成抽象方法,如果这个步骤是可选的,就做成虚方法,钩子。

    钩子可以让子类实现算法中的可选部分,或者在钩子对于子类的实现不那么重要的时候,子类可以对此钩子置之不理。钩子的另一个用法,是让子类能够有机会对模板方法中某些即将发生的步骤做出反应。钩子也可以让子类有能力为其抽象类做一些决定。

    最重要的一点:抽象类中的某些方法是可选的,对于这些可选的方法,就做成钩子,而不是做成抽象方法,这样就可以让子类的负荷减轻。

    新的设计原则:好莱坞设计原则——不要调用(打电话给)我们,我会调用(打电话给)你。

     

    好莱坞原则和模板方法

    他们两个的联系还算是比较明显:当我们设计模板方法时,我们告诉子类,“不要调用我们,我们会调用你”。

    好莱坞原则和依赖倒置原则之间的关系:

  • 相关阅读:
    创建struct类型的数组
    simulate windows touch input
    Could not load file using Ranorex runtime : General Questions
    UIAutomator 编译
    w3cmark前端精彩博文周报 10.27-11.2
    w3cmark前端精彩博文周报 10.20-10.27
    w3cmark前端精彩博文周报 10.13-10.19
    sublime自定义snippet代码片段
    Iconfont在移动端遇到问题的探讨
    一个小效果引出的兼容性探讨
  • 原文地址:https://www.cnblogs.com/pangjianxin/p/8758666.html
Copyright © 2020-2023  润新知