示例

当我们设计一个类时,我们能明确它对外提供的某个方法的内部执行步骤,

但一些步骤,不同的子类有不同的行为时,我们该如何来设计该类?

下面以玩王者荣耀为例展开学习:

玩游戏首先需要初始化游戏,然后加载地图、加载角色、然后才能开始游戏,最后结束游戏

定义一个Game类:

public abstract class Game {

    public final void play () {
initialize();
loadMap();
loadRole();
startPlay();
endPlay();
} /** 初始化游戏 */
protected abstract void initialize(); /** 加载地图 */
protected abstract void loadMap(); /** 加载角色 */
protected abstract void loadRole(); /** 开始游戏 */
protected abstract void startPlay(); /** 结束游戏 */
protected abstract void endPlay();
}

上面类的实现类:

public class KingGlory extends Game {

    @Override
protected void initialize() {
System.out.println("王者荣耀正在初始化,请稍后。。。");
} @Override
protected void loadMap() {
System.out.println("正在加载王者峡谷地图。。。");
} @Override
protected void loadRole() {
System.out.println("正在加载角色鲁班七号。。。");
} @Override
protected void startPlay() {
System.out.println("开始玩王者荣耀。。。");
} @Override
protected void endPlay() {
System.out.println("结束王者荣耀游戏,保存数据。。。");
}
}

测试类:

public class Test {
public static void main(String[] args) {
Game game = new KingGlory();
game.play();
}
}

模板方法模式

定义

一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行

意图

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

主要解决问题

一些方法通用,却在每一个子类都重新写了这一方法

适用场景

1、有多个子类共有的方法,且逻辑相同。

2、重要的、复杂的方法,可以考虑作为模板方法

优缺点

优点:

1、封装不变部分,扩展可变部分。

2、提取公共代码,便于维护。

3、行为由父类控制,子类实现。

缺点:

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

类图:



涉及的角色:

  1. 抽象模板(AbstractTemplate)角色:定义了一个或多个抽象操作,以便让子类实现,这些抽象操作叫基本操作,它们是顶级逻辑的组成步骤;定义并实现了一个模板方法,这个模板方法一般是一个具体方法,它给出了一个顶级逻辑的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类实现
  2. 具体模板(ContrateTemplate)角色:实现父类所定义的一个或多个抽象方法,它们是一个顶级逻辑的组成步骤;每一个抽象模板角色都可以有任意多个具体模板角色与之对应,而每一个具体模板角色都可以给出这些抽象方法的不同实现,从而使得顶级逻辑的实现各不相同

对应源码:

public abstract class AbstractTemplate {

    public void templateMethod() {
doOperation1(); doOperation2(); doOperation3();
} /** 基本方法,由子类实现 */
protected abstract void doOperation1(); /** 基本方法,由子类实现 */
protected abstract void doOperation2(); /** 基本方法,已经实现 */
private final void doOperation3(){
//do something......
}
}
public class ContrateTemplate extends AbstractTemplate {
@Override
protected void doOperation1() {
System.out.println("doOperation1......");
} @Override
protected void doOperation2() {
System.out.println("doOperation2......");
}
}

西天取经的九九八十一难

在《西游记》中,唐僧到西天取经途中所经历的八十一难,说到底,是观音菩萨所控制的一个项目,下面以上面场景为例,写一个小例子:

取经人所经历的劫难,每一步都是菩萨控制好的:

public abstract class LearnFromPeople {

    public final void westernCountry() {
firstHard();
secondHard();
thirdHard();
} /** 第一难 */
protected abstract void firstHard(); /** 第二难 */
protected abstract void secondHard(); /** 第三难 */
protected abstract void thirdHard();
}

唐僧去西天取经,继承了取经人这个抽象类,然后需要历经81难:

public class TangMonk extends LearnFromPeople {
@Override
protected void firstHard() {
System.out.println("金蝉遭贬第一难"); } @Override
protected void secondHard() {
System.out.println("出胎几杀第二难");
} @Override
protected void thirdHard() {
System.out.println("满月抛江第三难");
}
}

唐僧开始上路了:

public class Test {

    public static void main(String[] args) {
LearnFromPeople people = new TangMonk();
people.westernCountry();
}
}



需要注意的是,为了防止恶意的操作,模板方法上面都会加上final关键字

从西天取经的九九八十一难来看Java设计模式:模板方法模式的更多相关文章

  1. 歌乐第二弹:C++九九八十一

    第一弹传送门:极乐净土 二话不说,上代码(注意事项在第一弹里): #include <windows.h> //q前缀为低音,g为高音,s前缀为半音阶 const int q1 = 131 ...

  2. Tony老师带你来看Java设计模式:代理模式

    目录 定义 作用 意图 主要解决问题 优缺点 与装饰者模式的区别 结构 从Tony老师来看实现方式 静态代理 动态代理 JDK动态代理的实现 cglib动态代理的实现 定义 为其他对象提供一种代理来控 ...

  3. 从中国加入WTO来看Java设计模式:中介者模式

    目录 应用场景 中介者模式 定义 意图 主要解决问题 何时使用 优缺点 世界贸易组织WTO 应用场景 系统中对象之间存在比较复杂的引用关系,导致它们之间的依赖关系结构混乱而且难以复用该对象 想通过一个 ...

  4. 一起来看Java设计思想之23种设计模式

    目录 怎么使用设计模式 23种设计模式 创建型模式 结构型模式 行为型模式 总结 怎么使用设计模式 为什么要使用设计模式? 编写代码,写接口.写类.写方法 用设计模式做设计的作用是什么? 指导.规定如 ...

  5. 第三百八十一节,Django+Xadmin打造上线标准的在线教育平台—xadmin全局配置

    第三百八十一节,Django+Xadmin打造上线标准的在线教育平台—xadmin全局配置 1.xadmin主题设置 要使用xadmin主题,需要在一个app下的adminx.py后台注册文件里,写一 ...

  6. “全栈2019”Java第八十一章:外部类能否访问嵌套接口里的成员?

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  7. 孤荷凌寒自学python第八十一天学习爬取图片1

    孤荷凌寒自学python第八十一天学习爬取图片1 (完整学习过程屏幕记录视频地址在文末) 通过前面十天的学习,我已经基本了解了通过requests模块来与网站服务器进行交互的方法,也知道了Beauti ...

  8. 《手把手教你》系列基础篇(八十一)-java+ selenium自动化测试-框架设计基础-TestNG如何暂停执行一些case(详解教程)

    1.简介 在实际测试过程中,我们经常会遇到这样的情况,开发由于某些原因导致一些模块进度延后,而你的自动化测试脚本已经提前完成,这样就会有部分模块测试,有部分模块不能进行测试.这就需要我们暂时不让一些t ...

  9. Java设计模式(十一) 享元模式

    原创文章,同步发自作者个人博客 http://www.jasongj.com/design_pattern/flyweight/.转载请注明出处 享元模式介绍 享元模式适用场景 面向对象技术可以很好的 ...

随机推荐

  1. java荷兰国旗问题

    荷兰国旗包含三种颜色:红.白.蓝. 有三种颜色的球,算法的目标是将这三种球按颜色顺序正确地排列.它其实是三向切分快速排序的一种变种,在三向切分快速排序中,每次切分都将数组分成三个区间:小于切分元素.等 ...

  2. Nifi组件脚本开发—ExecuteScript 使用指南(三)

    上一篇:Nifi组件脚本开发-ExecuteScript 使用指南(二) Part 3 - 高级特征 本系列的前两篇文章涵盖了 flow file 的基本操作, 如读写属性和内容, 以及使用" ...

  3. MySQL5.7.29 和 Navicat ===> windows窗口式按装和使用

    MySQL windows窗口式按装下载方法:官网: https://www.mysql.com/ ==> DOWNLOADS ==> MySQL Community (GPL) Down ...

  4. shell编程基础二

    一.流程控制 while循环:只要条件满足一直循环 read -p "请输入一个数字:" white_data while [ ${white_data} -lt 20 ] do ...

  5. 报错: You are using pip version 10.0.1, however version 18.0 is available.

    报错: You are using pip version 10.0.1, however version 18.0 is available. You should consider upgradi ...

  6. SpringBoot(八):SpringBoot中配置字符编码 Springboot中文乱码处理

    SpringBoot中配置字符编码一共有两种方式 方式一: 使用传统的Spring提供的字符编码过滤器(和第二种比较,此方式复杂,由于时间原因这里先不介绍了,后续补上) 方式二(推荐使用) 在appl ...

  7. PAT-1167(Cartesian Tree)根据中序遍历序列重建最小堆

    Cartesian Tree PAT-1167 一开始我使用数组进行存储,但是这样可能会导致无法开足够大的数组,因为树如果是链表状的则无法开这么大的数组(虽然结点很少). 正确的解法还是需要建树,使用 ...

  8. there is nothing(i春秋CTF题解)

      (1)打开页面,显示为:there is nothing (2)抓包发现提示 (3)hint:ip,Large internal network 意为最大的内网网段IP,hint: ip,Larg ...

  9. VirtualBOX 虚拟机 FreeBSD配置

    pkg装virtualbox-ose-additions, 再将 Section "Device"Identifier "Card0"Driver " ...

  10. 【Azure API 管理】APIM CORS策略设置后,跨域请求成功和失败的Header对比实验

    在文章"从微信小程序访问APIM出现200空响应的问题中发现CORS的属性[terminate-unmatched-request]功能"中分析了CORS返回空200的问题后,进一 ...