• 设计模式篇——初探模板方法模式


    文章目录

    1、模版方法介绍
    2、模版方法类图
    3、模版方法例子的实现以及“钩子”方法
    4、模版方法模式总结

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

    类图

    接下来让我们看下它的类图、~~~~


    一个简单的Demo:

    故事从三只企鹅开始的:

     企鹅大胖,二虎,豆豆生活在遥远的南极,无忧无虑的生活着。而它们每天做的事就是 ->

        /// <summary>
        /// 企鹅大胖
        /// </summary>
        public class PenguinDaPang
        {
            public void SayHi(string Name, int Age)
            {
                Console.WriteLine($"我叫:{Name},我{Age}岁了,我每天要做的事是:");
            }
            public void DoSomethingOnDay()
            {
           SayHi("大胖",4); Eat(); Sleep(); BeatDoudou(); }
    public void Eat() { Console.WriteLine("我在吃金枪鱼"); } public void Sleep() { Console.WriteLine("我在睡觉"); } public void BeatDoudou() { Console.WriteLine("我在打豆豆"); } }
        /// <summary>
        /// 企鹅二虎
        /// </summary>
        public class PenguinErHu
        {
            public void SayHi(string Name, int Age)
            {
                Console.WriteLine($"我叫:{Name},我{Age}岁了,我每天要做的事是:");
            }
            public void DoSomethingOnDay()
            {
           SayHi("二虎",4); Eat(); Sleep(); BeatDoudou(); }
    public void Eat() { Console.WriteLine("我在吃三文鱼"); } public void Sleep() { Console.WriteLine("我在睡觉"); } public void BeatDoudou() { Console.WriteLine("我在打豆豆"); } }
        /// <summary>
        /// 企鹅豆豆
        /// </summary>
        public class PenguinDouDou
        {
            public void SayHi(string Name, int Age)
            {
                Console.WriteLine($"我叫:{Name},我{Age}岁了,我每天要做的事是:");
            }
            public void DoSomethingOnDay()
            {
           SayHi("豆豆",3); Eat(); Sleep();
    //BeatDoudou(); } public void Eat() { Console.WriteLine("我在吃比目鱼"); } public void Sleep() { Console.WriteLine("我在睡觉"); } //我并不打自己。。 //public void BeatDoudou() //{ // Console.WriteLine("我在打豆豆"); //} }

    没错,就是吃饭、睡觉,打豆豆,当然也会和你打个招呼

    接下来,让我们来优化下这段代码。 我们不难发现,每只企鹅都会执行相同的动作 “睡觉”,所有的企鹅都会“吃饭”,但是吃的食物可能不相同。这样,我们可以抽象一个“企鹅”类,这批企鹅都会吃饭和睡觉,于是:

      public abstract class Penguin
        {
            public void DoSomethingOnDay(string name,int age)
            {
                SayHi(name, age);
                Eat();
                Sleep();
            }
            public void SayHi(string Name, int Age)
            {
                Console.WriteLine($"我叫:{Name},我{Age}岁了,我每天要做的事是:");
            }
            void Sleep()
            {
                Console.WriteLine("睡觉....");
            }
            public abstract void Eat();
        }

    于是我们的三只企鹅又变成了这样:

        public class PenguinDaPang : Penguin
        {
            public override void Eat()
            {
                Console.WriteLine("我在吃金枪鱼");
            }
        }
        public class PenguinErHu : Penguin
        {
            public override void Eat()
            {
                Console.WriteLine("我在吃三文鱼");
            }
        }
        public class PenguinDouDou : Penguin
        {
            public override void Eat()
            {
                Console.WriteLine("我在吃比目鱼");
            }
        }

    来走一波~

    企鹅抽象类中,DoSomethingOnDay就是模板方法,它封装了一系列算法步骤,做到了代码的复用,对有变化的方法(例如Eat),延迟到子类去实现来适应不同的要求。

    但是问题又来了,我们的企鹅还有一件事没有做,“打豆豆”。这件事并不是每一只企鹅都做,但是它又应该在模板方法中(因为大多说企鹅都会做),这样我们应该怎么处理呢?

    模板方法给我们提供了一个方法叫做“钩子方法”,让我们先来看下修改后的代码。

    public abstract class Penguin
        {
            public void DoSomethingOnDay(string name, int age)
            {
                SayHi(name, age);
                Eat();
                Sleep();
                if (IsBeat())
                    BeatDoudou();
            }
            public void SayHi(string Name, int Age)
            {
                Console.WriteLine($"我叫:{Name},我{Age}岁了,我每天要做的事是:");
            }
            void Sleep()
            {
                Console.WriteLine("睡觉....");
            }
            public abstract void Eat();
            public abstract void BeatDoudou();  //敲打豆豆
    
            public virtual bool IsBeat()        //钩子方法
            {
                return true;
            }
        }
        public class PenguinDaPang : Penguin
        {
            public override void BeatDoudou()
            {
                Console.WriteLine("我在用树枝敲打豆豆");
            }
    
            public override void Eat()
            {
                Console.WriteLine("我在吃金枪鱼");
            }
        }
        public class PenguinErHu : Penguin
        {
            public override void BeatDoudou()
            {
                Console.WriteLine("我在用雪球敲打豆豆");
            }
    
            public override void Eat()
            {
                Console.WriteLine("我在吃三文鱼");
            }
        }
        public class PenguinDouDou : Penguin
        {
            public override bool IsBeat()                       //子类重写钩子方法
            {
                if (typeof(PenguinDouDou).Name == "PenguinDouDou")
                    return false;
                else
                    return true;
            }
            public override void BeatDoudou()
            {
                Console.WriteLine("我特么就是豆豆");
            }
    
            public override void Eat()
            {
                Console.WriteLine("我在吃比目鱼");
            }
        }
    View Code

    钩子方法是在超类中的一个默认实现,我们这里的IsBeat()方法,默认是返回true的。子类中的"豆豆"是不会打自己的,所以,我们可以重写IsBeat()方法,当类是 "豆豆"类的时候,就返回一个false,那样就不再执行 "打豆豆这个操作"。这就是钩子方法的作用,用来控制超类中是否要执行一些算法步骤,默认有实现,也可以由子类来重写它。

    ,跑起来~~~

    emmmmmm,现在我们知道了,钩子方法是高层类中一个默认实现的方法,它的作用是控制某些方法(算法步骤)是否执行,钩子方法也可以由子类去覆盖重写。


    总结:

    这就是一个简单的模版方法模式的例子了,现在让我们来总结下

    1、“模板方法”(DoSomethingOnday)定义了算法的步骤,并且将有些步骤地实现延迟到了子类;

    2、模板方法提供了代码重用的技巧

    3、模版方法的抽象类(超类)定义具体方法,抽象方法和钩子方法(虚方法),抽象方法由子类去实现,钩子方法可以由子类选择是否去覆盖它。

  • 相关阅读:
    二进制,八进制,十六进制,十进制之间的换算
    14简化路径(71)
    13字符串解码(394)
    12 反转每对括号间的子串(1190)
    11 使括号有效的最少添加(921)
    10 K 个一组翻转链表(25)
    9 从链表中删去总和值为零的连续节点(1171)
    8 链表中的下一个更大节点(1019)
    7两两交换链表中的节点(24)
    6 奇偶链表(
  • 原文地址:https://www.cnblogs.com/liumengchen-boke/p/8117446.html
Copyright © 2020-2023  润新知