设计模式篇——初探模板方法模式 文章目录

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、模版方法的抽象类(超类)定义具体方法,抽象方法和钩子方法(虚方法),抽象方法由子类去实现,钩子方法可以由子类选择是否去覆盖它。