设计模式轻松学【十三】模版方法模式

简介: 我们去银行办理业务一般要经过以下4个流程:取号、排队、办理具体业务、对银行工作人员进行评分等,其中取号、排队和对银行工作人员进行评分的业务对每个客户是一样的,可以在父类中实现,但是办理具体业务却因人而异,它可能是存款、取款或者转账等,可以延迟到子类中实现。

在面向对象程序设计过程中,程序员常常会遇到这种情况:设计一个系统时知道了算法所需的关键步骤,而且确定了这些步骤的执行顺序,但某些步骤的具体实现还未知,或者说某些步骤的实现与具体的环境相关。

模式定义与特点

  • 定义

    声明一个操作中的算法骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤。它是一种类行为型模式。

  • 参与角色

    • 抽象类(Abstract Class):负责给出一个算法的轮廓和骨架。它由一个模板方法和若干个基本方法构成。这些方法的定义如下。

      1. 模板方法:抽象类声明并实现,一般是定义算法的骨架,按某种顺序调用其包含的基本方法。并且,模版方法大多会定义为final类型,指明主要的逻辑功能在子类中不能被重写。
      2. 基本方法:是整个算法中的一个步骤,包含以下几种类型。

        • 抽象方法(abstractMethod):在抽象类中申明,可定义多个,由具体子类实现。
        • 具体方法(concreteMethod):抽象类中声明并实现,一般不建议子类实现
        • 钩子方法(hookMethod):抽象类中声明并给出空实现,子类可以选择性的进行扩展实现。
    • 具体子类(Concrete Class):实现抽象类中所定义的抽象方法和钩子方法,它们是一个顶级逻辑的一个组成步骤。
  • 类结构图

    image.png

  • 结构代码实现

    • 抽象模板

      abstract class AbstractTemplate {
          //1个模板方法,用于规定具体模板执行的步骤
          public void templateMethod() {
              //具体的方法调用可以调整,就好比先吃菜还是先吃饭,二者都可以
              abstractMethod();
              concreteMethod();
              hookMethod();
          }
          
          //多个基本方法
          //包括1...n个抽象,1个具体,1个钩子方法
          public abstract void abstractMethod();
          
          //具体方法,抽象类中声明并实现,不建议子类实现,一般设计成私有的
          private void concreteMethod() {
              System.out.println("父类具体的方法");
          }
          
          //钩子方法,抽象类中声明并给出空实现,子类可以选择性的实现
          public void hookMethod() {
              
          }
      }
    • 具体模板

      class ConcreteTemplate1 extends AbstractTemplate{
      
          @Override
          public void abstractMethod() {
              System.out.println("这是子类1的具体实现");
          }
      }
      
      class ConcreteTemplate2 extends AbstractTemplate {
      
          @Override
          public void abstractMethod() {
              System.out.println("这是子类2的具体实现");
          }
      }
    • 客户端调用程序

      public class TemplateMethodTest {
      
          public static void main(String[] args) {
              //使用第一个模板
              AbstractTemplate concreteTemplate1 = new ConcreteTemplate1();
              concreteTemplate1.templateMethod();
              //使用第二个模板方法
              AbstractTemplate concreteTemplate2 = new ConcreteTemplate2();
              concreteTemplate2.templateMethod();
          }
      }

模式实现分析

现在我们来实现去银行办理业务的案例,办理业务一般要经过以下4个流程:取号、排队、办理具体业务、对银行工作人员进行评分。除了办理具体业务不一样外,其他的流程一样,我们可以进行如下编程。

  • 声明抽象类

    abstract class AbstractBankHandler {
        //准备去办理业务
        public void prepareHandler() {
            //具体的方法调用可以调整,就好比先吃菜还是先吃饭,二者都可以
            getNumber();
            lineUp();
            handler();
            evaluate();
            hookMethod();
        }
        
        //多个基本方法
        //取号是一样的,所以直接实现,直接实现的方法建议声明为private
        private void getNumber() {
            System.out.println("取号");
        }
        //排队,一样的,所以直接实现
        private void lineUp() {
            System.out.println("慢慢长路在排队");
        }
        //办理业务,不一样,子类实现
        public abstract void handler();
        
        //评价,不一样,每个人的评价不一样
        public abstract void evaluate();
        
        //钩子方法,抽象类中声明并给出空实现,子类可以选择性的实现
        public void hookMethod() {
            
        }
    }
  • 声明具体类

    class PersonA extends AbstractBankHandler{
        @Override
        public void handler() {
            System.out.println("存200万");
        }
        @Override
        public void evaluate() {
            System.out.println("五星好评");
        }
    }
    
    class PersonB extends AbstractBankHandler {
    
        @Override
        public void handler() {
            System.out.println("取1000万");
        }
    
        @Override
        public void evaluate() {
            System.out.println("态度不好,差评");
        }
    }
  • 客户端调用

    public class TemplateMethodTest {
    
        public static void main(String[] args) {
            //使用第一个模板
            AbstractBankHandler personA = new PersonA();
            personA.prepareHandler();
            
            //使用第二个模板方法
            AbstractBankHandler personB = new PersonB();
            personB.prepareHandler();
        }
    }

通过上面程序,我们知道,对于流程相同,子类实现不同的操作我们可以采用模板方法模式来实现,这大大的提高了我们代码的复用率。

总结

  • 优点

    • 提高代码复用性,将相同部分的代码放在抽象的父类中,而将不同的代码放入不同的子类中
    • 实现了反向控制, 比较灵活。因为有钩子方法,因此,子类的实现也可以影响父类中主逻辑的运行。但是,在灵活的同时,由于子类影响到了父类,违反了里氏替换原则,也会给程序带来风险。这就对抽象类的设计有了更高的要求。
  • 缺点

    • 引入了抽象类,每一个不同的实现都需要一个子类来实现,导致类的个数增加,从而增加了系统实现的复杂度。
  • 应用场景

    • 在多个子类拥有相同的方法,并且这些方法逻辑相同时,可以考虑使用模版方法模式。在程序的主框架相同,细节不同的场合下,也比较适合使用这种模式。
目录
相关文章
|
16天前
|
设计模式 安全 Java
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
|
2月前
|
设计模式 数据库连接 PHP
PHP中的设计模式:提升代码的可维护性与扩展性在软件开发过程中,设计模式是开发者们经常用到的工具之一。它们提供了经过验证的解决方案,可以帮助我们解决常见的软件设计问题。本文将介绍PHP中常用的设计模式,以及如何利用这些模式来提高代码的可维护性和扩展性。我们将从基础的设计模式入手,逐步深入到更复杂的应用场景。通过实际案例分析,读者可以更好地理解如何在PHP开发中应用这些设计模式,从而写出更加高效、灵活和易于维护的代码。
本文探讨了PHP中常用的设计模式及其在实际项目中的应用。内容涵盖设计模式的基本概念、分类和具体使用场景,重点介绍了单例模式、工厂模式和观察者模式等常见模式。通过具体的代码示例,展示了如何在PHP项目中有效利用设计模式来提升代码的可维护性和扩展性。文章还讨论了设计模式的选择原则和注意事项,帮助开发者在不同情境下做出最佳决策。
|
18天前
|
设计模式 开发者 Python
Python编程中的设计模式:工厂方法模式###
本文深入浅出地探讨了Python编程中的一种重要设计模式——工厂方法模式。通过具体案例和代码示例,我们将了解工厂方法模式的定义、应用场景、实现步骤以及其优势与潜在缺点。无论你是Python新手还是有经验的开发者,都能从本文中获得关于如何在实际项目中有效应用工厂方法模式的启发。 ###
|
11天前
|
设计模式 安全 Java
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
30 1
|
1月前
|
设计模式 Java Kotlin
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
本教程详细讲解Kotlin语法,适合希望深入了解Kotlin的开发者。对于快速学习Kotlin语法,推荐查看“简洁”系列教程。本文重点介绍了构建者模式在Kotlin中的应用与改良,包括如何使用具名可选参数简化复杂对象的创建过程,以及如何在初始化代码块中对参数进行约束和校验。
21 3
|
2月前
|
设计模式 算法 安全
设计模式——模板模式
模板方法模式、钩子方法、Spring源码AbstractApplicationContext类用到的模板方法
设计模式——模板模式
|
2月前
|
设计模式 算法 PHP
PHP中的设计模式:策略模式的深入探索与实践在软件开发的广袤天地中,PHP以其独特的魅力和强大的功能,成为无数开发者手中的得力工具。而在这条充满挑战与机遇的征途上,设计模式犹如一盏明灯,指引着我们穿越代码的迷雾,编写出更加高效、灵活且易于维护的程序。今天,就让我们聚焦于设计模式中的璀璨明珠——策略模式,深入探讨其在PHP中的实现方法及其实际应用价值。
策略模式,这一设计模式的核心在于它为软件设计带来了一种全新的视角和方法。它允许我们在运行时根据不同情况选择最适合的解决方案,从而极大地提高了程序的灵活性和可扩展性。在PHP这门广泛应用的编程语言中,策略模式同样大放异彩,为开发者们提供了丰富的创作空间。本文将从策略模式的基本概念入手,逐步深入到PHP中的实现细节,并通过一个具体的实例来展示其在实际项目中的应用效果。我们还将探讨策略模式的优势以及在实际应用中可能遇到的挑战和解决方案,为PHP开发者提供一份宝贵的参考。
|
2月前
|
设计模式 数据库连接 PHP
PHP中的设计模式:如何提高代码的可维护性与扩展性在软件开发领域,PHP 是一种广泛使用的服务器端脚本语言。随着项目规模的扩大和复杂性的增加,保持代码的可维护性和可扩展性变得越来越重要。本文将探讨 PHP 中的设计模式,并通过实例展示如何应用这些模式来提高代码质量。
设计模式是经过验证的解决软件设计问题的方法。它们不是具体的代码,而是一种编码和设计经验的总结。在PHP开发中,合理地使用设计模式可以显著提高代码的可维护性、复用性和扩展性。本文将介绍几种常见的设计模式,包括单例模式、工厂模式和观察者模式,并通过具体的例子展示如何在PHP项目中应用这些模式。
|
2月前
|
设计模式 Java Spring
spring源码设计模式分析-代理设计模式(二)
spring源码设计模式分析-代理设计模式(二)
|
1月前
|
设计模式 安全 Java
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
35 0