深入浅出设计模式-009:模板方法模式(Template Method Pattern)

    技术2025-01-19  7

    深入浅出设计模式-009:模板方法模式(Template Method Pattern)

    一:如泡茶喝泡咖啡,步骤都一样,四部    class Coffee{        public void prepareRecipe(){            boilWater();            brewCoffeeGrinds();            pourInCup();            addSugarAndMilk();        }        public void boilWater(){            Console.WriteLine("boilWater");        }        public void brewCoffeeGrinds(){            Console.WriteLine("brewCoffeeGrinds");        }        public void pourInCup(){            Console.WriteLine("pourInCup");        }        public void addSugarAndMilk(){            Console.WriteLine("addSugarAndMilk");        }    }    class Tea{        public void prepareRecipe(){            boilWater();            steepTeaBag();            pourInCup();            addLenmon();        }        public void boilWater(){            Console.WriteLine("boilWater");        }        public void steepTeaBag(){            Console.WriteLine("brewCoffeeGrinds");        }        public void pourInCup(){            Console.WriteLine("pourInCup");        }        public void addLenmon(){            Console.WriteLine("addSugarAndMilk");        }    }

    二:第一步和第三步是一样的,可以抽象出来    abstract class CaffeineBeverage{        public abstract void prepareRecipe();

            public void boilWater(){            Console.WriteLine("boilWater");        }        public void pourInCup(){            Console.WriteLine("pourInCup");        }    }    class Coffee : CaffeineBeverage{        public override void prepareRecipe(){            boilWater();            brewCoffeeGrinds();            pourInCup();            addSugarAndMilk();        }        public void brewCoffeeGrinds(){            Console.WriteLine("brewCoffeeGrinds");        }        public void addSugarAndMilk(){            Console.WriteLine("addSugarAndMilk");        }    }    class Tea : CaffeineBeverage{        public override void prepareRecipe(){            boilWater();            steepTeaBag();            pourInCup();            addLenmon();        }        public void steepTeaBag(){            Console.WriteLine("brewCoffeeGrinds");        }        public void addLenmon(){            Console.WriteLine("addSugarAndMilk");        }    }

    三:将第二步和第四步统一命名,这样就可以将prepareRecipe提到抽象类中    abstract class CaffeineBeverage{        //模板方法,定义步骤        public void prepareRecipe(){            boilWater();            brew();            pourInCup();            addConditiments();        }

            public abstract void brew();        public abstract void addConditiments();

            public void boilWater(){            Console.WriteLine("boilWater");        }        public void pourInCup(){            Console.WriteLine("pourInCup");        }    }    class Coffee : CaffeineBeverage{        public override void brew(){            Console.WriteLine("brewCoffeeGrinds");        }        public override void addConditiments(){            Console.WriteLine("addSugarAndMilk");        }    }    class Tea : CaffeineBeverage{        public override void brew(){            Console.WriteLine("brewCoffeeGrinds");        }        public override void addConditiments(){            Console.WriteLine("addSugarAndMilk");        }    }

    四:模板方法模式:在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。    模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。    abstract class AbstractClass    {        void templateMethod()        {            primitiveOperation1();            primitiveOperation2();            concreateOperation();        }        abstract void primitiveOperation1();        abstract void primitiveOperation2();        void concreateOperation() { 添加实现};    }

    五:引入钩子    1: 钩子是一种被声明在抽象类中的方法,但是有空的或者默认的实现。        钩子的存在可疑让子类有能力对算法的不同点进行挂钩。要不要挂钩,由子类决定        abstract class AbstractClass        {            void templateMethod()            {                primitiveOperation1();                primitiveOperation2();                concreateOperation();                hook();            }            abstract void primitiveOperation1();            abstract void primitiveOperation2();            void concreateOperation() { 添加实现}            void hook(){}        }    2: 当子类“必须”提供算法中某个方法或步骤时,就是用抽象方法。        如果算法的这个部分是可选的,就用钩子。        如果是钩子的话,子类就可以选择实现这个钩子,但是并不强制这么做,应为提供默认实现了。    3: 钩子的作用        钩子可以让子类实现算法中的可选部分。        当钩子对于子类的实现并不重要的时候,子类可以对钩子置之不理。        子类能够有激活对模板方法中的某些即将发生的步骤做出反应。

    六:钩子的应用    abstract class CaffeineBeverage{        public void prepareRecipe(){            boilWater();            brew();            pourInCup();            if (customerWantsCondiments()){                addConditiments();            }        }        public abstract void brew();        public abstract void addConditiments();        public void boilWater(){            Console.WriteLine("boilWater");        }        public void pourInCup(){            Console.WriteLine("pourInCup");        }        //定义空的缺省实现        //子类可以覆盖这个方法,但不一定见得要这么做        public virtual Boolean customerWantsCondiments(){            return true;        }    }    class Coffee : CaffeineBeverage{        public override void brew(){            Console.WriteLine("brewCoffeeGrinds");        }        public override  void addConditiments(){            Console.WriteLine("addSugarAndMilk");        }        public override bool customerWantsCondiments(){            //用户自行控制是否加入甜点            //此处可以做成用户按键输入的            return false;        }    }    class Tea : CaffeineBeverage{        public override  void brew(){            Console.WriteLine("brewCoffeeGrinds");        }        public override  void addConditiments(){            Console.WriteLine("addSugarAndMilk");        }        public override bool customerWantsCondiments(){            //用户自行控制是否加入甜点            //此处可以做成用户按键输入的            return true;        }    }

    七:设计原则:好莱坞原则:别调用(打电话给)我们,我们会调用(打电话给)你。    即允许低层组件将自己挂钩到系统上,但是高层组件会决定什么时候和怎样使用这些顶层组件。

    最新回复(0)