设计模式 – 行为型之王 – 模板方法模式

“四人帮”23种设计模式可分为三大类:创建型,结构型,行为型。每种模式中都有一个最常用的模式,例如,创建型中最常用的是工厂方法模式,结构型模式中最常用的是适配器模式,行为型模式中最常用的是模板方法模式,本节重点讲解模板方法模式。

模板方法模式是最简单的设计模式,起这样的一个名字听起来可能感觉很专业,其实只要大家写过面向对象,就一定熟悉这个模式。说的更简单一点,只要抽象基类中定义了一个受保护的Abastract方法,并提供一个公开的访问接口(供子类访问),然后让子类去重写这个抽象方法,就是模板方法模式最常见的应用。

为什么要用到模板方法模式呢?我们知道,通常写代码的时候,通常一个方法里面会包含几个子方法,但是其中一个方法,在基类中并不知道它具体有什么用途,只能由子类去决定具体要做什么事情,但是在基类中,我们必须按照事情的先后顺序执行(事件1->事件2->事件3->事件4),才能符合正常流程,如下图:

设计模式 - 行为型之王 - 模板方法模式

要执行的方法如下:
设计模式 - 行为型之王 - 模板方法模式设计模式 - 行为型之王 - 模板方法模式

1 /// <summary>
 2 /// schedule template
 3 /// </summary>
 4 abstract class Schedule
 5 {
 6     public void Execute()
 7     {
 8         ExecuteThings1();
 9         ExecuteThings2();
10         ExecuteThings3();
11         ExecuteThings4();
12     }
13 
14     private void ExecuteThings1()
15     {
16         //execute the concrete thing for Things1
17         //such as: Print something.
18     }
19 
20     private void ExecuteThings3()
21     {
22         //execute the concrete thing for Things3
23         //such as : access the database
24     }
25 
26     private void ExecuteThings4()
27     {
28         //execute the concrete thing for Things4
29         //write something to the EventViewer
30     }
31 
32     private void ExecuteThings2()
33     {
34         //do nothing
35     }
36 }

View Code
可是ExecuteThings2()方法我们不知道要做什么,这时候怎么办呢,直接写成吧,等于写了一个空方法,啥也都执行,并且当子类要继续时也不能根据具体执行什么东东来重写这个方法,这个方法并不能在动态运行时有多种表现,不满足多态的特点。
设计模式 - 行为型之王 - 模板方法模式设计模式 - 行为型之王 - 模板方法模式

1         private void ExecuteThings2()
2         {
3             //do nothing
4         }

View Code
为了达到子类按需定制,就是大家常说的“钩子”效果,可以首先将方法申明为virtual/abstract,以便子类重写,因为这个方法是一个抽象方法(空方法,什么也不做,等同于C++中的纯虚函数),所以将该方法申明为abstract抽象方法,为了便于子类重写,而不被外界访问,我们使用保护修饰符protected,达到钩子效果,代码如下:
设计模式 - 行为型之王 - 模板方法模式设计模式 - 行为型之王 - 模板方法模式

1 /// <summary>
 2 /// schedule template
 3 /// </summary>
 4 abstract class Schedule
 5 {
 6     public void Execute()
 7     {
 8         ExecuteThings1();
 9         ExecuteThings2();
10         ExecuteThings3();
11         ExecuteThings4();
12     }
13 
14     private void ExecuteThings1()
15     {
16         //execute the concrete thing for Things1
17         //such as: Print something.
18     }
19 
20     private void ExecuteThings3()
21     {
22         //execute the concrete thing for Things3
23         //such as : access the database
24     }
25 
26     private void ExecuteThings4()
27     {
28         //execute the concrete thing for Things4
29         //write something to the EventViewer
30     }
31 
32     private void ExecuteThings2()
33     {
34         //call the hook
35         DoExecuteThings2();
36     }
37 
38     /// <summary>
39     /// hook method, the sub inherited class will implement the details.
40     /// </summary>
41     protected abstract void DoExecuteThings2();
42 
43 }

View Code
于是,子类可以按需重写他自己想要执行的事情。
设计模式 - 行为型之王 - 模板方法模式设计模式 - 行为型之王 - 模板方法模式

1 class GroupASchedule : Schedule
 2 {
 3     protected override void DoExecuteThings2()
 4     {
 5         Console.WriteLine("{0} -> we will execute my plan for GroupA!", this.GetType().Name);
 6     }
 7 }
 8 
 9 class GroupBSchedule : Schedule
10 {
11     protected override void DoExecuteThings2()
12     {
13         Console.WriteLine("{0} -> we will execute my plan for GroupB!", this.GetType().Name);
14     }
15 }

View Code
从而,实现了想做的具体事情2。

示例代码: YearlyArrangement.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Template
{
    abstract class YearlyArrangement
    {
        protected virtual void Work()
        {
            Console.WriteLine("Most of the time, we are working!");
        }

        /// <summary>
        /// hook method
        /// sub-class should override this method
        /// </summary>
        protected abstract void MakeEntertainmentEveryYear();

        protected virtual void AwardPrize()
        {
            Console.WriteLine("At the end of each year, the company holds an award-prize ceremony!");
        }

        protected virtual void AttendAnnualMeeting()
        {
            Console.WriteLine("At the end of each year, the company holds an annual meeting!");
        }

        public void MakePlan()
        {
            Console.WriteLine("Year: {0}", this.GetType().Name.Replace("Year", string.Empty));
            Work();
            MakeEntertainmentEveryYear();
            AwardPrize();
            AttendAnnualMeeting();
            Console.WriteLine();
        }
    }
}

Year2013.cs:

class Year2013 : YearlyArrangement
{
    protected override void MakeEntertainmentEveryYear()
    {
        Console.WriteLine("Travelling to America!");
    }
}

Year2014.cs:

class Year2014 : YearlyArrangement
{
    protected override void MakeEntertainmentEveryYear()
    {
        Console.WriteLine("Travelling to Paris!");
    }
}

Year2015.cs:

class Year2015 : YearlyArrangement
{
    protected override void MakeEntertainmentEveryYear()
    {
        Console.WriteLine("Go to lenovo for learning!");
    }
}

主函数Program.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Template
{
    class Program
    {
        static void Main(string[] args)
        {
            Test();
        }

        static void Test()
        {
            YearlyArrangement year = new Year2013();
            year.MakePlan();

            year = new Year2014();
            year.MakePlan();

            year = new Year2015();
            year.MakePlan();
            Console.ReadKey();
        }
    }
}

运行效果:

设计模式 - 行为型之王 - 模板方法模式

源代码下载: https://capps.codeplex.com/releases/view/107754

由于水平有限,难免有描述不够准确之处,欢迎大家指正。

原文链接: https://www.cnblogs.com/Bowl2008/archive/2013/06/08/template_method_design_patterns.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/91675

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月10日 上午1:17
下一篇 2023年2月10日 上午1:17

相关推荐