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

简介: 我们去银行办理业务一般要经过以下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();
        }
    }

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

总结

  • 优点

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

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

    • 在多个子类拥有相同的方法,并且这些方法逻辑相同时,可以考虑使用模版方法模式。在程序的主框架相同,细节不同的场合下,也比较适合使用这种模式。
目录
相关文章
|
7月前
|
设计模式 Java 数据库连接
【设计模式】【创建型模式】工厂方法模式(Factory Methods)
一、入门 什么是工厂方法模式? 工厂方法模式(Factory Method Pattern)是一种创建型设计模式,它定义了一个用于创建对象的接口,但由子类决定实例化哪个类。工厂方法模式使类的实例化延迟
224 16
|
7月前
|
设计模式 负载均衡 监控
并发设计模式实战系列(2):领导者/追随者模式
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发设计模式实战系列,第二章领导者/追随者(Leader/Followers)模式,废话不多说直接开始~
231 0
|
7月前
|
设计模式 监控 Java
并发设计模式实战系列(1):半同步/半异步模式
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发设计模式实战系列,第一章半同步/半异步(Half-Sync/Half-Async)模式,废话不多说直接开始~
212 0
|
7月前
|
设计模式 安全 Java
并发设计模式实战系列(12):不变模式(Immutable Object)
🌟 大家好,我是摘星!🌟今天为大家带来的是并发设计模式实战系列,第十二章,废话不多说直接开始~
187 0
|
7月前
|
设计模式 算法 Java
设计模式觉醒系列(04)策略模式|简单工厂模式的升级版
本文介绍了简单工厂模式与策略模式的概念及其融合实践。简单工厂模式用于对象创建,通过隐藏实现细节简化代码;策略模式关注行为封装与切换,支持动态替换算法,增强灵活性。两者结合形成“策略工厂”,既简化对象创建又保持低耦合。文章通过支付案例演示了模式的应用,并强调实际开发中应根据需求选择合适的设计模式,避免生搬硬套。最后推荐了JVM调优、并发编程等技术专题,助力开发者提升技能。
|
7月前
|
设计模式 Prometheus 监控
并发设计模式实战系列(20):扇出/扇入模式(Fan-Out/Fan-In)(完结篇)
🌟 大家好,我是摘星!🌟今天为大家带来的是并发设计模式实战系列,第二十章,废话不多说直接开始~
259 0
|
11月前
|
设计模式
「全网最细 + 实战源码案例」设计模式——模式扩展(配置工厂)
该设计通过配置文件和反射机制动态选择具体工厂,减少硬编码依赖,提升系统灵活性和扩展性。配置文件解耦、反射创建对象,新增产品族无需修改客户端代码。示例中,`CoffeeFactory`类加载配置文件并使用反射生成咖啡对象,客户端调用时只需指定名称即可获取对应产品实例。
236 40
|
9月前
|
设计模式 Java 关系型数据库
设计模式:工厂方法模式(Factory Method)
工厂方法模式是一种创建型设计模式,通过将对象的创建延迟到子类实现解耦。其核心是抽象工厂声明工厂方法返回抽象产品,具体工厂重写该方法返回具体产品实例。适用于动态扩展产品类型、复杂创建逻辑和框架设计等场景,如日志记录器、数据库连接池等。优点包括符合开闭原则、解耦客户端与具体产品;缺点是可能增加类数量和复杂度。典型应用如Java集合框架、Spring BeanFactory等。
|
11月前
|
设计模式 关系型数据库
「全网最细 + 实战源码案例」设计模式——工厂方法模式
简单工厂模式是一种创建型设计模式,通过一个工厂类根据传入参数创建不同类型的产品对象,也称“静态工厂方法”模式。其结构包括工厂类、产品接口和具体产品类。适用于创建对象种类较少且调用者无需关心创建细节的场景。优点是封装性强、代码复用性好;缺点是扩展性差,增加新产品时需修改工厂类代码,违反开闭原则。
176 15
|
11月前
|
设计模式 Java
「全网最细 + 实战源码案例」设计模式——生成器模式
生成器模式(Builder Pattern)是一种创建型设计模式,用于分步骤构建复杂对象。它允许用户通过控制对象构造的过程,定制对象的组成部分,而无需直接实例化细节。该模式特别适合构建具有多种配置的复杂对象。其结构包括抽象建造者、具体建造者、指挥者和产品角色。适用于需要创建复杂对象且对象由多个部分组成、构造过程需对外隐藏或分离表示与构造的场景。优点在于更好的控制、代码复用和解耦性;缺点是增加复杂性和不适合简单对象。实现时需定义建造者接口、具体建造者类、指挥者类及产品类。链式调用是常见应用方式之一。
179 12

热门文章

最新文章