用心理解设计模式——模板方法模式 (Template Method Pattern)

前置文章: 设计模式的原则 

其他设计模式:用心理解设计模式专栏

设计模式相关代码已统一放至 我的 Github

 

一、定义

  行为型模式之一。

  Define the skeleton of an algorithm in an operation, deferring some steps to subclass. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.

(在操作中定义一个算法的框架,将一些步骤延迟到子类中,使得子类可以不改变算法结构即可重新定义该算法的某些特定步骤。)

二、结构解析

  模板方法模式的一般结构有两种角色: 抽象类、具体类。

  抽象类(AbstractClass):定义模板方法,模板方法将程序的执行步骤总结出来并固定, 然后直接实现其中的不变步骤,将可变的步骤声明为抽象方法,具体的实现延迟至子类。

  具体类(ConcreteClass):实现抽象父类中定义的抽象步骤。

三、评价

  模板方法模式是典型的面向抽象编程,在抽象阶段将系统的不变部分(如步骤顺序)确定下来,变化部分(如步骤具体内容)交给子类。

  模板方法模式很常见,可参考,蝇量模式 、装饰器模式责任链模式 示例代码中的使用。

四、钩子方法

  钩子方法常出现在模板方法模式中,顾明思意,它就是一个钩子。

  钩子可以在定义时就挂着东西(父类可有实现),可以在后来看情况挂上别的东西(子类可重写),也可以总是不挂任何东西(父类中无实现,并且子类中未重写或重写无实现)。

  钩子方法应该是一个虚方法,因为虚方法才可以在定义时能够选择性实现,并且可以让子类选择性重写(注意,抽象方法无法直接给出实现,并且子类必须重写,不然会有编译错误。所以抽象方法虽然可以作为钩子方法,但不是太适合,不完美)。

  虚方法的注意事项,请参考 设计模式的原则 中 里氏替换原则部分的描述。

  一定要注意,钩子方法应该不是关键步骤,不阻碍模板主干运行,它是一种 “可选的、附加的” 的存在。

五、实现

using UnityEngine;

namespace TemplateMethod
{
    public abstract class AbstractClass
    {
        //模板方法,将不变的行为(一般是步骤)总结出来。(子类不要重写这个方法)
        public void TemplateMethod()
        {
            DoStep1();
            DoStep2();
            DoStep3();
            Hook();
            DoStep4();
        }

        //其中,某些步骤是不变的,某些步骤是可变的。
        //不变的,直接给出实现,
        //可变的,在子类中确定具体的执行内容。
        private void DoStep1() { Debug.Log("DoStep1"); }            //不变的。
        public abstract void DoStep2();                             //可变的,实现延迟至子类。
        public abstract void DoStep3();                             //可变的,实现延迟至子类。

        //钩子方法。固定出现在某个地方,一般不是重要的关键步骤,父类可选择有实现或无实现,子类可选择重写或不重写。
        protected virtual void Hook() { Debug.Log("DoAfter3AndBefor4_XXX"); }  

        private void DoStep4() { Debug.Log("DoStep4"); }            //不变的。
    }

    //具体类A
    public class ConcreteClassA : AbstractClass
    {
        public override void DoStep2()
        {
            Debug.Log("DoStep2_A");
        }

        public override void DoStep3()
        {
            Debug.Log("DoStep3_A");
        }
    }
    
    //具体类B
    public class ConcreteClassB : AbstractClass
    {
        public override void DoStep2()
        {
            Debug.Log("DoStep2_B");
        }

        public override void DoStep3()
        {
            Debug.Log("DoStep3_B");
        }

        sealed protected override void Hook()          //可看情况,选择设置为密封方法
        {
            Debug.Log("DoAfter3AndBefor4_B");
        }
    }
    
    public class Client
    {
        static public void Main()
        {
            new ConcreteClassA().TemplateMethod();  //输出 DoStep1 DoStep2_A DoStep3_A DoAfter3AndBefor4_XXX DoStep4 
            new ConcreteClassB().TemplateMethod();  //输出 DoStep1 DoStep2_B DoStep3_B DoAfter3AndBefor4_B DoStep4 
        }
    }
}

 

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
内容简介: 设计模式是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。 本课程内容定位学习设计原则,学习设计模式的基础。在实际开发过程中,并不是一定要求所有代码都遵循设计原则,我们要考虑人力、时间、成本、质量,不是刻意追求完美,要在适当的场景遵循设计原则,体现的是一种平衡取舍,帮助我们设计出更加优雅的代码结构。本章将详细介绍开闭原则(OCP)、依赖倒置原则(DIP)、单一职责原则(SRP)、接口隔离原则(ISP)、迪米特法则(LoD)、里氏替换原则(LSP)、合成复用原则(CARP)的具体内容。 为什么需要学习这门课程? 你在日常的开发中,会不会也遇到过同样的问题。系统出现问题,不知道问题究竟出在什么位置;当遇到产品需求,总是对代码缝缝补补,不能很快的去解决。而且平时工作中,总喜欢把代码堆在一起,出现问题时,不知道如何下手,工作效率很低,而且自己的能力也得不到提升。而这些都源于一个问题,那就是软件设计没做好。这门课能帮助你很好的认识设计模式,让你的能力得到提升。课程大纲: 为了让大家快速系统了解设计模式知识全貌,我为您总结了思维导图,帮您梳理学习重点,建议收藏!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NRatel

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值