Java通俗易懂系列设计模式之模板模式

实际开发中常常会遇到,代码骨架类似甚至相同,只是具体的实现不一样的场景。例如:流程都有开启、编辑、驳回、结束。每个流程都包含这几个步骤,不同的是不同的流程实例它们的内容不一样。共享单车都是先开锁、骑行、上锁、付款。这些大的步骤固定,不同的是每个实例的具体实现细节不一样。这些类似的业务我们都可以使用模板模式实现。为什么要使用模板模式以及如何使用呢?

介绍

定义:在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。

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

  • 主要解决:一些方法通用,却在每一个子类都重新写了这一方法。
  • 何时使用:有一些通用的方法。
  • 如何解决:将这些通用算法抽象出来。
  • 关键代码:在抽象类实现,其他步骤在子类实现。

实现

我们以生活中买菜做饭的例子来写个Demo,烧饭一般都是买菜、洗菜、烹饪、装盘四大过程。中国自古有八大菜系,制作方式肯定都避不开这四个过程。那在模板模式中如何实现呢?
创建一个抽象类,它的模板方法被设置为 final。为防止恶意操作,一般模板方法都加上 final 关键词。

public abstract class AbstractCookingService {
    //买菜
    protected abstract void shopping();
    //清洗
    protected abstract void wash();
    //烹饪
    protected abstract void cooking();
    //装盘
    protected abstract void dishedUp();

    public final void process() {
        shopping();
        wash();
        cooking();
        dishedUp();
    }
}

创建实现了上述抽象类的子类。
// 徽菜烹饪

/**
 * 徽菜制作大厨
 */
public class HuiCaiChef extends AbstractCookingService {

    @Override
    protected void shopping() {
        System.out.println("买菜:新鲜鱼一条,红辣椒五两");
    }

    @Override
    protected void wash() {
        System.out.println("清洗:红椒洗净切片,鱼头半分");
    }

    @Override
    protected void cooking() {
        System.out.println("烹饪:鱼头水蒸,辣椒过油");
    }

    @Override
    protected void dishedUp() {
        System.out.println("装盘:用长形盘子装盛");
    }
}

// 川菜烹制

/**
 * 川菜制作大厨
 */
public class HuiCaiChef extends AbstractCookingService {

    @Override
    protected void shopping() {
        System.out.println("买菜:黑猪肉一斤,蒜头5个");
    }

    @Override
    protected void wash() {
        System.out.println("清洗:猪肉洗净,蒜头去皮");
    }

    @Override
    protected void cooking() {
        System.out.println("烹饪:大火翻炒,慢火闷油");
    }

    @Override
    protected void dishedUp() {
        System.out.println("装盘:深碗盛起,热油浇拌");
    }
}

使用 TemplatePatternDemo 类执行模板方法 process() 来演示烹饪的定义方式。

public class TemplatePatternDemo {

    public static void main(String[] args) {
        System.out.println("----------川菜制作------------");
        AbstractCookingService chuanCaiService = new ChuanCaiChef();
        chuanCaiService.process();
        System.out.println("-----------徽菜制作-----------");
        AbstractCookingService huiCaiService = new HuiCaiChef();
        huiCaiService.process();
    }
}

执行程序,输出结果:

----------川菜制作------------

买菜:新鲜鱼一条,红辣椒五两

清洗:红椒洗净切片,鱼头半分

烹饪:鱼头水蒸,辣椒过油

装盘:用长形盘子装盛

-----------徽菜制作-----------

买菜:黑猪肉一斤,蒜头5个

清洗:猪肉洗净,蒜头去皮

烹饪:大火翻炒,慢火闷油

从以上实例可以看出,其实模板模式也没什么高深莫测的,简单来说就是三大步骤:

  1. 创建一个抽象类,定义几个抽象方法和一个final修饰的模板方法,而模板方法中设定了抽象方法的执行顺序或逻辑。
  2. 无论子类有多少个,只需要继承该抽象类,实现父类的抽象方法重写自己的业务。
  3. 根据不同的需求创建不同的子类实现,每次调用的地方只需调用模板方法,即可完成特定的模板流程。

总结

从以上的分析和Demo我们可以看到,模板方法提高了我们的代码的可维护性和可扩展性。有优点也有缺点。
优点:

  1. 封装不变部分,扩展可变部分。
  2. 提取公共代码,便于维护。
  3. 行为由父类控制,子类实现。

缺点:

每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。

使用场景:

  • 有多个子类共有的方法,且逻辑相同。
  • 重要的、复杂的方法,可以考虑作为模板方法。

以上就是Java通俗易懂系列设计模式之模板模式的详细内容,更多关于Java设计模式的资料请关注我们其它相关文章!

(0)

相关推荐

  • 浅谈JAVA设计模式之代理模式

    代理模式 在代理模式(Proxy Pattern)中,一个类代表另一个类的功能.这种类型的设计模式属于结构型模式. 在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口. 介绍 意图: 为其他对象提供一种代理以控制对这个对象的访问. 主要解决: 在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上.在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时

  • Java设计模式之观察者模式原理与用法详解

    本文实例讲述了Java设计模式之观察者模式原理与用法.分享给大家供大家参考,具体如下: 什么是观察者模式 可以这么理解: 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象. 这个主题对象在状态上发生变化时,会通知所有观察者对象,让它们能够自动更新自己. 也可以这样理解: 观察者模式是关于多个对象想知道一个对象中数据变化情况的一种成熟模式.观察者模式中有一个称作"主题"的对象和若干个称作"观察者"的对象,"主题"和&qu

  • 详解JAVA设计模式之模板模式

    在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板.它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行.这种类型的设计模式属于行为型模式. 介绍 意图:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤. 主要解决:一些方法通用,却在每一个子类都重新写了这一方法. 何时使用:有一些通用的方法. 如何解决:将这些通用算法抽象出来. 关键代码:在抽象类实现,其他步骤在子

  • Java抽象类的构造模板模式用法示例

    本文实例讲述了Java抽象类的构造模板模式用法.分享给大家供大家参考,具体如下: 一 点睛 模板模式的一些简单规则. 抽象父类可以只定义需要使用的某些方法,而不能实现的部分抽象成抽象方法,留给子类去实现. 父类中可能包含需要调用其他系列方法的方法,这些被调方法既可以由父类实现,也可以由其子类实现.父类里提供的方法只是定义了一个通用算法,其实现也许并不完全由自身实现,而必须依赖器子类的辅助. 二 实战 1 父类 public abstract class SpeedMeter { // 转速 pr

  • Java设计模式 模板模式及应用场景解析

    模板模式,顾名思义,就是通过模板拓印的方式. 定义模板,就是定义框架.结构.原型.定义一个我们共同遵守的约定. 定义了模板,我们的剩余工作就是对其进行充实.丰润,完善它的不足之处. 定义模板采用抽象类来定义,公共的结构化逻辑需要在抽象类中完成,只将非公共的部分逻辑抽象成抽象方法,留待子类充实实现. 所以上文所述不足之处就是这些抽象方法. 总的来说,模板模式就是通过抽象类来定义一个逻辑模板,逻辑框架.逻辑原型,然后将无法决定的部分抽象成抽象类交由子类来实现,一般这些抽象类的调用逻辑还是在抽象类中完

  • 详解JAVA设计模式之适配器模式

    适配器模式 适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁.这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能. 这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能.举个真实的例子,读卡器是作为内存卡和笔记本之间的适配器.您将内存卡插入读卡器,再将读卡器插入笔记本,这样就可以通过笔记本来读取内存卡. 我们通过下面的实例来演示适配器模式的使用.其中,音频播放器设备只能播放 mp3 文件,通过使用一个更高级的音频播放器来播放 vlc 和 mp4

  • 浅谈JAVA设计模式之享元模式

    享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能.这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式. 享元模式尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象.我们将通过创建 5 个对象来画出 20 个分布于不同位置的圆来演示这种模式.由于只有 5 种可用的颜色,所以 color 属性被用来检查现有的 Circle 对象. 介绍 意图: 运用共享技术有效地支持大量细粒度的对象. 主要解决: 在有大量

  • 轻松掌握Java模板模式

    定义:一个抽象类公开定义了执行它的方法的方式/模板.它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行 特点: 1.封装不变部分,扩展可变部分. 2.提取公共代码,便于维护. 3.行为由父类控制,子类实现. 企业级开发和常用框架中的应用:spring中对hibernate的实现(开启事务,打开会话,关闭session) 实例:下面以玩游戏举例,所有游戏玩的时候都有两个操作,打开游戏和关闭游戏,但中间玩的方式就不一样了,下面看实际例子. public class Demo { pub

  • 一文看懂JAVA设计模式之工厂模式

    工厂顾名思义就是创建产品,根据产品是具体产品还是具体工厂可分为简单工厂模式和工厂方法模式,根据工厂的抽象程度可分为工厂方法模式和抽象工厂模式.该模式用于封装和管理对象的创建,是一种创建型模式.本文从一个具体的例子逐步深入分析,来体会三种工厂模式的应用场景和利弊. 1. 简单工厂模式 该模式对对象创建管理方式最为简单,因为其仅仅简单的对不同类对象的创建进行了一层薄薄的封装.该模式通过向工厂传递类型来指定要创建的对象,其UML类图如下: 下面我们使用手机生产来讲解该模式: Phone类:手机标准规范

  • Java设计模式之模板模式(Template模式)介绍

    Template模式定义:定义一个操作中算法的骨架,将一些步骤的执行延迟到其子类中. 其实Java的抽象类本来就是Template模式,因此使用很普遍.而且很容易理解和使用,我们直接以示例开始: 复制代码 代码如下: public abstract class Benchmark { /** * 下面操作是我们希望在子类中完成 */ public abstract void benchmark(); /** * 重复执行benchmark次数 */ public final long repea

  • 详解JAVA 设计模式之状态模式

    在状态模式(State Pattern)中,类的行为是基于它的状态改变的.这种类型的设计模式属于行为型模式. 在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context 对象. 介绍 意图: 允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类. 主要解决: 对象的行为依赖于它的状态(属性),并且可以根据它的状态改变而改变它的相关行为. 何时使用: 代码中包含大量与对象状态有关的条件语句. 如何解决: 将各种具体的状态类抽象出来. 关键代码: 通常

  • 实例讲解JAVA设计模式之备忘录模式

    在讲述这个模式之前,我们先看一个案例:游戏回档 游戏的某个场景,一游戏角色有生命力.攻击力.防御力等数据,在打Boss前和后会不一样,我们允许玩家如果感觉与Boss决斗的效果不理想,可以让游戏恢复到决斗前.下面是代码: 游戏角色类,用来存储角色的生命力.攻击力.防御力的数据. public class GameRole { private int vit;//生命力 private int atk;//攻击力 private int def;//防御力 //状态显示 public void st

随机推荐