模板模式(Template Pattern)

模板模式:别给我打电话,我会打给你。


场景:使用模板模式实现泡茶和冲咖啡的两个类似行为。


//抽象基类作为模板

    //以作为咖啡因饮品作为茶与咖啡的泛化类
    public abstract class CaffeineBeverage
    {
        //提供唯一的准备饮品的方法
        public void prepareRecipe()
        {
            //流程模板:烧水,冲泡,入杯,加调料
            boilWater();
            brew();
            pourInCup();
            if (customerWantsCondiments())
            {
                addCondiments();
            }
        }
        //抽象方法:冲泡
        protected abstract void brew(); 
        //抽象方法:加调料
        protected abstract void addCondiments();
        //公共方法:将水烧沸腾
        void boilWater()
        {
            Console.WriteLine("将水烧至沸腾");
        }
        //公共方法:将饮料导入杯中
        void pourInCup()
        {
            Console.WriteLine("将饮料导入杯中");
        }
        //钩子方法:用户是否想加入调料
        protected virtual bool customerWantsCondiments()
        {
            return true;
        }
    }

//实现模板的具体类

    public class Coffee:CaffeineBeverage
    {
        protected override void brew()
        {
            Console.WriteLine("倒入速溶咖啡粉末,并搅拌");
        }

        protected override void addCondiments()
        {
            Console.WriteLine("加入奶精和方块糖");
        }
        //钩子函数实现:子类实现但仍然由父类去调用,而不是调用父类
        protected override bool customerWantsCondiments()
        {
            string answer = getUserInput();
            if (answer.Equals("y"))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        private string getUserInput()
        {
            string answer = null;
            Console.Write("您是否需要加入奶精和方块糖(y/n)?");
            answer = Console.ReadLine();
            return answer;
        }
    }

    public class Tea : CaffeineBeverage
    {
        protected override void brew()
        {
            Console.WriteLine("倒入茶叶,浸泡");
        }

        protected override void addCondiments()
        {
            Console.WriteLine("加入柠檬");
        }

        protected override bool customerWantsCondiments()
        {
            string answer = getUserInput();
            if (answer.Equals("y"))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        private string getUserInput()
        {
            string answer = null;
            Console.Write("您是否需要加入柠檬(y/n)?");
            answer = Console.ReadLine();
            return answer;
        }
    }

测试用例:

        static void Main(string[] args)
        {
            CaffeineBeverage cafferneBeverage = null;
            while (true)
            {
                Console.WriteLine("您需要一些咖啡因饮品,请选择具体饮品,按回车键确认:");
                Console.WriteLine("1.一杯咖啡");
                Console.WriteLine("2.一杯茶");
                string answer = Console.ReadLine();
                if (answer.Equals("1"))
                {
                    cafferneBeverage = new Coffee();
                }
                else if (answer.Equals("2"))
                {
                    cafferneBeverage = new Tea();
                }
                else
                {
                    return;
                }             
                cafferneBeverage.prepareRecipe();
                Console.WriteLine("按您的要求,准备好了饮品!!\n");
            }
        }
测试结果:


总结:

1.“模板方法”定义了算法的步骤,把这些步骤的实现延迟到子类。

2.模板方法模式为我们提供了一种代码复用的重要技巧。

3.模板方法的抽象类可以定义具体方法、抽象方法和钩子。

4.抽象方法由子类实现。

5.钩子是一种方法,它在抽象类中不做事,或者只做默认的事情,子类可以选择要不要去覆盖它。

6.好莱坞原则告诉我们,将决策权放在高层模块中,以便决定如何以及何时调用低层模块。

7.你将在真实世界代码中看到模块方法模式的许多变体,不要期待他们全都是一眼就可以被你认出的。(如LIST的sort方法)

8.策略模式和模板方法模式都封装算法,一个用组合,一个用继承。

9.工厂方法是模板方法的一种特殊版本。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值