GOF设计模式-对象行为型模式-模板模式

26 篇文章 0 订阅
20 篇文章 0 订阅

在现实生活中,很多事情都包含几个实现步骤,例如请客吃饭,无论吃什么,一般都包含点 单、吃东西、买单等几个步骤,通常情况下这几个步骤的次序是:点单 --> 吃东西 --> 买单。 在这三个步骤中,点单和买单大同小异,最大的区别在于第二步——吃什么?吃面条和吃满 汉全席可大不相同。

 

在软件开发中,有时也会遇到类似的情况,某个方法的实现需要多个步骤(类似“请客”),其 中有些步骤是固定的(类似“点单”和“买单”),而有些步骤并不固定,存在可变性(类似“吃 东西”)。为了提高代码的复用性和系统的灵活性,可以使用一种称之为模板方法模式的设计 模式来对这类情况进行设计,在模板方法模式中,将实现功能的每一个步骤所对应的方法称 为基本方法(例如“点单”、“吃东西”和“买单”),而调用这些基本方法同时定义基本方法的执 行次序的方法称为模板方法(例如“请客”)。在模板方法模式中,可以将相同的代码放在父类 中,例如将模板方法“请客”以及基本方法“点单”和“买单”的实现放在父类中,而对于基本方 法“吃东西”,在父类中只做一个声明,将其具体实现放在不同的子类中,在一个子类中提 供“吃面条”的实现,而另一个子类提供“吃满汉全席”的实现。通过使用模板方法模式,一方面 提高了代码的复用性,另一方面还可以利用面向对象的多态性,在运行时选择一种具体子 类,实现完整的“请客”方法,提高系统的灵活性和可扩展性。

模板方法模式定义如下:


模板方法模式:定义一个操作中算法的框架,而将一些步骤延迟到子类中。模板方法模 式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

模板方法模式是一种基于继承的代码复用技术,它是一种类行为型模式。
模板方法模式是结构最简单的行为型设计模式,在其结构中只存在父类与子类之间的继承关 系。通过使用模板方法模式,可以将一些复杂流程的实现步骤封装在一系列基本方法中,在 抽象父类中提供一个称之为模板方法的方法来定义这些基本方法的执行次序,而通过其子类 来覆盖某些步骤,从而使得相同的算法框架可以有不同的执行结果。模板方法模式提供了一 个模板方法来定义算法框架,而某些具体步骤的实现可以在其子类中完成。

模板方法模式结构与实现

模式结构

模板方法模式结构比较简单,其核心是抽象类和其中的模板方法的设计,其结构如图所示:

模板方法模式包含如下两个角色:

(1) AbstractClass(抽象类):在抽象类中定义了一系列基本操作(PrimitiveOperations),这些基 本操作可以是具体的,也可以是抽象的,每一个基本操作对应算法的一个步骤,在其子类中 可以重定义或实现这些步骤。同时,在抽象类中实现了一个模板方法(Template Method),用于 定义一个算法的框架,模板方法不仅可以调用在抽象类中实现的基本方法,也可以调用在抽 象类的子类中实现的基本方法,还可以调用其他对象中的方法。
(2) ConcreteClass(具体子类):它是抽象类的子类,用于实现在父类中声明的抽象基本操作 以完成子类特定算法的步骤,也可以覆盖在父类中已经实现的具体基本操作。

 

应用举例:

车的启动到停止的过程

一台铃木的小车锋驭和一台铃木的摩托车风暴1000,我要想把这两种类型的车都先跑起来再停下来,有一些步骤,并且这些步骤是有先后顺序的,那就是:

1. 打开车门

2. 启动发动机

3. 挂档

4. 走起

5. 刹车

6. 停车

 

UML:

模板抽象类

package com.singland.dp.template;

public abstract class DriveTemplate {
    
    public final void drive() {
        openDoor();
        startEngine();
        gear();
        go();
        brake();
        stop();
    }
    
    protected abstract void openDoor();
    
    protected void startEngine() {
        System.out.println("engine started !");
    }
    
    protected abstract void gear();
    
    protected void go() {
        System.out.println("running...");
    }
    
    protected abstract void brake();
    
    protected void stop() {
        System.out.println("stopped !");
    }
}

小车锋驭的实现

package com.singland.dp.template;

public class SuzukiScross extends DriveTemplate {

    @Override
    protected void openDoor() {
        System.out.println("keyless entry");
    }

    @Override
    protected void gear() {
        System.out.println("gear with hand");
    }

    @Override
    protected void brake() {
        System.out.println("brake with foot");
    }
}

摩托车风暴1000的具体实现

package com.singland.dp.template;

public class SuzukiStrom1000 extends DriveTemplate {

    @Override
    protected void openDoor() {
        System.out.println("no door actually");
    }

    @Override
    protected void gear() {
        System.out.println("gear with foot");
    }

    @Override
    protected void brake() {
        System.out.println("brake with hand");
    }
}

客户端的测试代码就很简单了

package com.singland.dp.template;

import org.junit.Test;

public class MyTest {
    
    @Test
    public void test() {
//        DriveTemplate template = new SuzukiStrom1000();
        DriveTemplate template = new SuzukiScross();
        template.drive();
    }
}

运行结果:

 

模板方法模式效果与适用场景
模板方法模式是基于继承的代码复用技术,它体现了面向对象的诸多重要思想,是一种使用 较为频繁的模式。模板方法模式广泛应用于框架设计中,以确保通过父类来控制处理流程的 逻辑顺序(如框架的初始化,测试流程的设置等)。
5.1 模式优点
模板方法模式的主要优点如下:
(1) 在父类中形式化地定义一个算法,而由它的子类来实现细节的处理,在子类实现详细的处理算法时并不会改变算法中步骤的执行次序。

(2) 模板方法模式是一种代码复用技术,它在类库设计中尤为重要,它提取了类库中的公共行 为,将公共行为放在父类中,而通过其子类来实现不同的行为,它鼓励我们恰当使用继承来 实现代码复用。
(3) 可实现一种反向控制结构,通过子类覆盖父类的钩子方法来决定某一特定步骤是否需要执 行。
(4) 在模板方法模式中可以通过子类来覆盖父类的基本方法,不同的子类可以提供基本方法的 不同实现,更换和增加新的子类很方便,符合单一职责原则和开闭原则。
5.2 模式缺点
模板方法模式的主要缺点如下:
需要为每一个基本方法的不同实现提供一个子类,如果父类中可变的基本方法太多,将会导 致类的个数增加,系统更加庞大,设计也更加抽象,此时,可结合桥接模式来进行设计。
5.3 模式适用场景
在以下情况下可以考虑使用模板方法模式:
(1) 对一些复杂的算法进行分割,将其算法中固定不变的部分设计为模板方法和父类具体方 法,而一些可以改变的细节由其子类来实现。即:一次性实现一个算法的不变部分,并将可 变的行为留给子类来实现。
(2) 各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。
(3) 需要通过子类来决定父类算法中某个步骤是否执行,实现子类对父类的反向控制。

 

 

 

 

 

 

 


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值