设计模式

序号 内容 链接地址
1 设计模式七大原则 https://blog.csdn.net/qq_39668819/article/details/115390615
2 创建型设计模式–工厂模式 https://blog.csdn.net/qq_39668819/article/details/115375928
3 创建型设计模式–抽象工厂模式 https://blog.csdn.net/qq_39668819/article/details/115390992
4 创建型设计模式–单例模式 https://blog.csdn.net/qq_39668819/article/details/115396191
5 创建型设计模式–建造者模式 https://blog.csdn.net/qq_39668819/article/details/115396212
6 创建型设计模式—原型模式 https://blog.csdn.net/qq_39668819/article/details/115396227
7 结构型设计模式—代理模式 https://blog.csdn.net/qq_39668819/article/details/115480346
8 结构型设计模式—适配器模式 https://blog.csdn.net/qq_39668819/article/details/115499090
9 结构型设计模式—桥接模式 https://blog.csdn.net/qq_39668819/article/details/115560823
10 结构型设计模式—装饰模式 https://blog.csdn.net/qq_39668819/article/details/115582291
11 结构型设计模式—外观模式 https://blog.csdn.net/qq_39668819/article/details/115643900
12 结构型设计模式—享元模式 https://blog.csdn.net/qq_39668819/article/details/115680930
13 结构型设计模式—组合模式 https://blog.csdn.net/qq_39668819/article/details/115720713
14 行为型设计模式—模板方法模式 https://blog.csdn.net/qq_39668819/article/details/115774426
15 行为型设计模式—策略模式 https://blog.csdn.net/qq_39668819/article/details/115804292
16 行为型设计模式—命令模式 https://blog.csdn.net/qq_39668819/article/details/115877361
17 行为型设计模式—责任链模式 https://blog.csdn.net/qq_39668819/article/details/115981287
18 行为型设计模式—状态模式 https://blog.csdn.net/qq_39668819/article/details/116077215
19 行为型设计模式—观察者模式 https://blog.csdn.net/qq_39668819/article/details/116141223
20 行为型设计模式—中介者模式 https://blog.csdn.net/qq_39668819/article/details/116177694
21 行为型设计模式—迭代器模式 https://blog.csdn.net/qq_39668819/article/details/116213033
22 行为型设计模式—访问者模式 https://blog.csdn.net/qq_39668819/article/details/116246907
23 行为型设计模式—备忘录模式 https://blog.csdn.net/qq_39668819/article/details/116333844
24 行为型设计模式—解释器模式 https://blog.csdn.net/qq_39668819/article/details/116379466

行为型模式

行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。

行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。

模板方法模式

在现实生活中存在这样一类情景:去银行或营业厅办业务一般有如下流程:取号、排队、办理业务、然后对服务进行评价,其中取号、排队和对银行工作人员进行评分的业务对每个客户是一样的,而办理的具体业务却因人而异,如去银行可能去取款、存款、转账;去营业厅可能买手机、充话费、办宽带等等。又比如我们拨打 10086 流程:拨号、办理业务、评价、挂断电话;其中拨号、评价、挂断电话对每一个客户是一样的,而办理业务有可能不同,如:查话费、查流量、办理套餐、解锁欠费的卡等等;还比如:简历的模板【模板一样但简历不同】,论文的模板,考试的试卷【试题一样但个人答案不同】等等;我们把这些规定了流程或格式的实例定义成模板,允许使用者根据自己的需求去更新它,关于这一类问题我们都可以使用模板方法模式来处理。

在程序设计过程中,我们可能常常遇到这种情况::设计一个系统时知道了算法所需的关键步骤,而且确定了这些步骤的执行顺序,但某些步骤的具体实现还未知,或者说某些步骤的实现与具体的环境相关。这时我们就可以将知道的算法的关键步骤抽离出来作为模板,其中未知的实现作为抽象方法封装在模板中,在子类实现它的具体细节。

模板方法在 Java 中的典型实例是编发编程中的 AbstractQueuedSynchronizer 抽象队列同步器,其中的模板方法定义了同步组件的基本流程,而具体实现可以通过重写或实现其中的基本方法来实现【主要是 tryAcquiretryReleasetryAcquireSharedtryReleaseSharedisHeldExclusively 等方法】;主要参照 ReentrantLock,具体可以参考我前面写的关于并发编程方面的博客。

模式的定义

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

模式的优点:

  • 封装了不变的公共部分,扩展可变部分。它把认为是不变部分的算法封装到了父类中实现,而把可变的部分算法由子类实现,便于子类继续扩展。
  • 实现了最大化代码复用。父类的模板方法和已实现的某些步骤会被子类继承而直接使用。
  • 既统一了算法,也提供了很大的灵活性。父类的模板方法确保了算法的结构保持不变,同时由子类提供部分步骤的实现。
  • 提供了一个基本框架,容易扩展子类。模板方法有框架控制如何做事情,而由使用框架的人指定框架算法中每个步骤的细节。子类只要继承父类,实现抽象方法,就可以使用父类的算法

缺点:

  • 对每个不同的实现都需要定义一个子类,这会导致类的个数增加,系统更加庞大,设计也更加抽象,间接地增加了系统实现的复杂度。

  • 模板方法使用继承方式复用代码,如果要在基本算法里面增加一个步骤,而该步骤是抽象的话,每个子类都要修改代码,实现这个步骤。

  • 父类中的抽象方法由子类实现,子类执行的结果会影响父类的结果,这导致一种反向的控制结构,它提高了代码阅读的难度。

模式的结构

模板方法模式主要包含以下角色:

  • 抽象模板(AbstractClass):负责给出一个算法骨架,它由一个模板方法和若干个基本方法【具体方法、钩子方法、抽象方法】组成。模版方法一般是一个具体方法,它给出了一个顶级逻辑的骨架,而逻辑的一些组成步骤在相应的抽象操作中,推迟到子类实现,当然模板方法也有可能调用一些具体方法。

    • 模板方法:定义了算法的骨架,按照某种顺序调用其基本方法。
    • 具体方法:在抽象类中已经实现,在具体子类中可以继承或重写。
    • 钩子方法:在抽象类中已经实现,包含用于判断的逻辑方法和需要子类重写的方法两种
    • 抽象方法:在抽象类中声明,需要具体子类实现的方法,它是可变算法的具体实现部分。
  • 具体实现(ConcreteClass):实现父类所定义的一个或多个抽象方法。每一个 AbstractClass 都可以有任意多个 ConereteClass 与之对应,而每一个 ConcreteClass 都可以给出这些抽象方法(也就是顶级逻辑的组成步骤)的不同实现,从而使得顶级逻辑的实现各不相同。

模式的 UML 图如下:

模式的使用

这里我们以奶茶的制作【并非真正的奶茶制作过程,仅为模式介绍的实例】为例介绍模板方法的使用。

在本实例中,我们定义了一个制作奶茶的抽象类 TeaWithMilk ,里面包含了一个模板方法 makingTeaWithMilk() ,该方法中包含了制作奶茶流程中的各个基本方法,其中有些方法的处理对于各个奶茶类都一样,所以直接在抽象类中实现;但是有些方法的处理是不一样的【addIngredients()】,所以就交给具体的子类实现。

  • 抽象模板:TeaWithMilk 提供了一个制作奶茶的模板方法,以及若干个基本方法,其中添加配料的方法需要具体子类根据实际情况实现。
  • 具体实现:HoneyGrapefruitTeaMeatyGrapeTeaRawMilkTea,实现了添加配料方法的具体细节,其中 RawMilkTea 由于不需要添加配料,通过重写钩子方法 isFlag() 并返回 false 来跳过添加配料的步骤。
/**
* 抽象模板 - 奶茶制作抽象类
*/
public abstract class TeaWithMilk {/*** 模板方法 - 制作奶茶*/final public void makingTeaWithMilk() {addTea();addMilk();addWater();if (isFlag()) {addIngredients();}packaging();}/*** 具体方法 - 添加茶叶*/public void addTea() {System.out.println("第一步,添加茶叶");}/*** 具体方法 - 添加牛奶*/public void addMilk() {System.out.println("第二步,添加牛奶");}/*** 具体方法 - 添加水*/public void addWater() {System.out.println("第三步,添加水");}/*** 抽象方法 - 添加配料*/public abstract void addIngredients();/*** 具体方法 - 打包*/public void packaging() {System.out.println("最后一步,打包");}/*** 钩子方法 - 是否添加配料* @return*/public boolean isFlag() {return true;}
}/**
* 具体实现 - 蜂蜜柚子茶
*/
public class HoneyGrapefruitTea extends TeaWithMilk{@Overridepublic void addIngredients() {System.out.println("第四步,加入蜂蜜与西柚");}
}
/**
* 多肉葡萄茶
*/
public class MeatyGrapeTea extends TeaWithMilk{@Overridepublic void addIngredients() {System.out.println("第四步,加入多肉与葡萄");}
}
/**
* 具体实现 - 原味奶茶
*/
public class RawMilkTea extends TeaWithMilk{@Overridepublic void addIngredients() {}/*** 重写钩子方法实现 - 不添加配料* @return*/@Overridepublic boolean isFlag() {return false;}
}/**
* 模板方法测试类
*/
public class TemplateTest {public static void main(String[] args) {TeaWithMilk honeyGrapefruitTea = new HoneyGrapefruitTea();System.out.println("制作蜂蜜柚子奶茶: ");honeyGrapefruitTea.makingTeaWithMilk();System.out.println();TeaWithMilk meatyGrapeTea = new MeatyGrapeTea();System.out.println("制作多肉葡萄奶茶: ");meatyGrapeTea.makingTeaWithMilk();System.out.println();TeaWithMilk rawMilkTea = new RawMilkTea();System.out.println("制作原味奶茶: ");rawMilkTea.makingTeaWithMilk();}
}

运行程序,结果如下:

总结:

不变的和可变的行为在方法的子类实现中混合在一起的时候,不变的行为就会在子类中重复出现。模板方法模式是通过把不变行为搬移到超类,去除子类中的重复代码,帮助子类摆脱重复的不变行为的纠缠。这大大提高了代码的复用。【如上述示例的:添加茶叶、添加牛奶、添加水、打包这几个方法】

钩子方法

在模板方法模式的父类中,我们可以定义一个方法,它默认不做任何事,子类可以视情况要不要覆盖它,该方法称为 “钩子;就比如上述实例中的 isFlag() 方法。

钩子方法的作用:

  • 让子类实现算法中的可选部分。算法中的某些步骤是可选的,子类可以做出决定是否需要这些步骤。
  • 如果钩子对于子类的实现不重要时,子类可以对钩子置之不理。
  • 钩子可以让子类能够有机会对模板方法中某些即将发生的(或刚刚发生的)步骤作出反应。可以在钩子中实现我们对于某个步骤执行需要作出的动作,模板方法的某个步骤执行时,调用钩子。
  • 可以使得子类控制父类的行为。
模式的应用场景

模板方法模式主要有以下应用场景:

  • 算法的整体步骤很固定,但其中个别部分易变时,这时候可以使用模板方法模式,将容易变的部分抽象出来,供子类实现。
  • 当多个子类存在公共的行为时,可以将其提取出来并集中到一个公共父类中以避免代码重复。首先,要识别现有代码中的不同之处,并且将不同之处分离为新的操作。最后,用一个调用这些新的操作的模板方法来替换这些不同的代码。
  • 当需要控制子类的扩展时,模板方法只在特定点调用钩子操作,这样就只允许在这些点进行扩展。

行为型设计模式---模板方法模式相关推荐

  1. Java设计模式之行为型:模板方法模式

    一.什么是模板方法模式: 模板方法是基于继承实现的,在抽象父类中声明一个模板方法,并在模板方法中定义算法的执行步骤(即算法骨架).在模板方法模式中,可以将子类共性的部分放在父类中实现,而特性的部分延迟 ...

  2. 在一个程序设计里,不同的功能窗口有着相似的功能实现方式,可采用设计模式---模板方法模式

        前段时间学习了一些设计模式,最近在做项目的过程中恰巧用到了其中的一个--模板方法模式.这个模式在程序设计过程中可是为小编省去了不少的代码量呢.具体是怎样应用的呢?接下来小编为您分享. 前面博文 ...

  3. 『设计模式』瑞幸咖啡还是星巴克,一杯下午茶让我明白 设计模式--模板方法模式(Template Method Pattern)

    23种设计模式+额外常用设计模式汇总 (持续更新) 简介 Define the skeleton of an algorithm in an operation,deferring some step ...

  4. 『设计模式』设计模式--模板方法模式

    23种设计模式+额外常用设计模式汇总 (持续更新) 简介 Define the skeleton of an algorithm in an operation,deferring some step ...

  5. Java设计模式-模板方法模式详解

    Java设计模式-模板方法模式 文章目录 Java设计模式-模板方法模式 0.前言 1.模板方法原理 2.模板方法模式中的角色 3.模板方法模式的UML类图 4.代码实现 5.编码测试 6.模板模式中 ...

  6. Java设计模式 - 模板方法模式

    Java设计模式 - 模板方法模式 定义一个算法的骨架,并将一些步骤通过子类表达. UML图示 要点 1. 定义一个算法的骨架 - 建立一个抽象类 2. 将一些步骤通过子类表达 - 子类继承抽象类 赋 ...

  7. linkin大话设计模式--模板方法模式

    linkin大话设计模式--模板方法模式 准备一个抽象类,将部分逻辑以具体方法的形式实现,然后申明一些抽象方法来迫使子类实现剩余的逻辑.不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不 ...

  8. 【设计模式】行为型02模板方法模式(Template Method Patten)

    五一长假,没有出去,不喜欢嘈杂的人群,玩了会游戏发泄了下憋在心底的戾气,手旁大马克杯里是母亲泡的绿茶.点开自己的播放列表,耳机里传来的是理查德克莱德曼的致爱丽丝.自己是个凡人,卑微渺小的活着.不说废话 ...

  9. 模板设计模式_设计模式-模板方法模式

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

最新文章

  1. 罗兰贝格84页白皮书:一文看懂中国ICT产业新黄金十年
  2. python速成一小时_Python学习|一小时快速入门python(一)
  3. 32位x86处理器编程导入——《x86汇编语言:从实模式到保护模式》读书笔记08
  4. 十二月份找工作好找吗_淘宝美工前景怎么样?好找工作吗?
  5. C#并发编程之初识并行编程
  6. 怎样做外链有利于关键词排名?
  7. python如何创建自定义模块_Python学习之如何引用Python自定义模块?
  8. Fbank特征与MFCC特征解析
  9. c语言2059,C语言错误 error C2059: 语法错误:“)”以及 错误error C2065: “sockaddr”: 未声明的标识符...
  10. 祝贺丨openGauss正式亮相,云和恩墨发布可公开下载的容器镜像
  11. linux查看80端口连接ip,Linux通过netstat命令查看80端口连接数的方法
  12. 基于快速傅里叶变换实现的狗声识别器(人工智能)
  13. 逆变电源于滤波电感器
  14. js 当天24小时倒计时
  15. linux下读取excel文件
  16. 《高级数据库系统》学习笔记
  17. endnote导出格式下载地址
  18. 论文精读--Autoformer
  19. 必修三计算机选修三知识点,高二数学必修三知识点归纳总结
  20. CAD —— 二次开发环境搭建(arx)

热门文章

  1. f2fs系列文章fsck(四)
  2. 基于C语言控制台程序的简易MP3音乐播放器
  3. openflow交换机 ryu_ryu(示例代码)
  4. Caffe 代码解读之全连接层 inner product layer
  5. Android性能优化之解密ZAKER,网易云阅读等新闻应用的内容缓存加载方式
  6. xtrabackup 命令详解
  7. arduino ps2摇杆程序_Arduino技巧之PS2摇杆实验
  8. CSS魔法堂:重新认识Box Model、IFC、BFC和Collapsing margins
  9. PHP编码规范【json159】
  10. Python爬取手机壁纸