概述
流程图
模板方法(Template Method)模式的定义如下:定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。它是一种类行为型模式。
在面向对象系统的分析与设计过程中经常会遇到这样一种情况:对于某一个业务逻辑(算法实现) 在不同的对象中有不同的细节实现, 但是逻辑(算法) 的框架(或通用的应用算法)是相同的。 Template 提供了这种情况的一个实现框架。Template 模式是采用继承的方式实现这一点:将逻辑(算法) 框架放在抽象基类中, 并定义好细节的接口,子类中实现细节。
Template 模式实际上就是利用面向对象中多态的概念实现算法实现细节和高层接口的松耦合。可以看到 Template 模式采取的是继承方式实现这一点的,由于继承是一种强约束性的条件,因此也给 Template 模式带来一些许多不方便的地方
Template 模式获得一种反向控制结构效果, 这也是面向对象系统的分析和设计中一个原则 DIP(依赖倒置: Dependency Inversion Principles)。 其含义就是父类调用子类的操(高
层模块调用低层模块的操作),低层模块实现高层模块声明的接口。这样控制权在父类(高
层模块),低层模块反而要依赖高层模块。
继 承 的 强 制 性 约 束 关 系 也 让 Template 模 式 有 不 足 的 地 方 , 我 们 可 以 看 到 对 于ConcreteClass 类中的实现的原语方法 Primitive1(),是不能被别的类复用。假设我们要创建一个 AbstractClass 的变体 AnotherAbstractClass,并且两者只是通用算法不一样,其原语操作想复用 AbstractClass 的子类的实现。但是这是不可能实现的,因为 ConcreteClass 继承自AbstractClass,也就继承了 AbstractClass 的通用算法, AnotherAbstractClass 是复用不了ConcreteClass 的实现,因为后者不是继承自前者。Template 模式暴露的问题也正是继承所固有的问题, Strategy 模式则通过组合(委托)来达到和 Template 模式类似的效果, 其代价就是空间和时间上的代价,
摘自《二十三种设计模式》
代码
我们将创建一个定义操作的 Game 抽象类,其中,模板方法设置为 final,这样它就不会被重写。Cricket 和 Football 是扩展了 Game 的实体类,它们重写了抽象类的方法
package design.template;
/**
* 模板方法(Template Method)模式的定义如下:
* 定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,
* 使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。
* <p>
* 举个例子
* 我们将创建一个定义操作的 Game 抽象类,其中,模板方法设置为 final,这样它就不会被重写。
* Cricket 和 Football 是扩展了 Game 的实体类,它们重写了抽象类的方法。
*/
public class TemplatePattern {
public static void main(String[] args) {
Game game = new Cricket();
game.play();
System.out.println();
game = new Football();
game.play();
}
}
abstract class Game {
abstract void initialize();
abstract void startPlay();
abstract void endPlay();
//模板,此处用final,防止被误操作
public final void play() {
//初始化游戏
initialize();
//开始游戏
startPlay();
//结束游戏
endPlay();
}
}
class Cricket extends Game {
@Override
void endPlay() {
System.out.println("Cricket Game Finished!");
}
@Override
void initialize() {
System.out.println("Cricket Game Initialized! Start playing.");
}
@Override
void startPlay() {
System.out.println("Cricket Game Started. Enjoy the game!");
}
}
class Football extends Game {
@Override
void endPlay() {
System.out.println("Football Game Finished!");
}
@Override
void initialize() {
System.out.println("Football Game Initialized! Start playing.");
}
@Override
void startPlay() {
System.out.println("Football Game Started. Enjoy the game!");
}
}
运行结果:
Cricket Game Initialized! Start playing.
Cricket Game Started. Enjoy the game!
Cricket Game Finished!
Football Game Initialized! Start playing.
Football Game Started. Enjoy the game!
Football Game Finished!
模式的扩展
在模板方法模式中,基本方法包含:抽象方法、具体方法和钩子方法,正确使用“钩子方法”可以使得子类控制父类的行为。如下面例子中,可以通过在具体子类中重写钩子方法 HookMethod1() 和 HookMethod2() 来改变抽象父类中的运行结果
package design.template;
// 在模板方法模式中,基本方法包含:抽象方法、具体方法和钩子方法,正确使用“钩子方法”可以使得子类控制父类的行为。
// 如下面例子中,可以通过在具体子类中重写钩子方法 HookMethod1() 和 HookMethod2() 来改变抽象父类中的运行结果
public class HookTemplateMethod {
public static void main(String[] args) {
HookAbstractClass tm = new HookConcreteClass();
tm.TemplateMethod();
}
}
//含钩子方法的抽象类
abstract class HookAbstractClass {
//模板方法
public void TemplateMethod() {
abstractMethod1();
HookMethod1();
if (HookMethod2()) {
SpecificMethod();
}
abstractMethod2();
}
//具体方法
public void SpecificMethod() {
System.out.println("抽象类中的具体方法被调用...");
}
//钩子方法1
public void HookMethod1() {
}
//钩子方法2
public boolean HookMethod2() {
return true;
}
//抽象方法1
public abstract void abstractMethod1();
//抽象方法2
public abstract void abstractMethod2();
}
//含钩子方法的具体子类
class HookConcreteClass extends HookAbstractClass {
public void abstractMethod1() {
System.out.println("抽象方法1的实现被调用...");
}
public void abstractMethod2() {
System.out.println("抽象方法2的实现被调用...");
}
public void HookMethod1() {
System.out.println("钩子方法1被重写...");
}
public boolean HookMethod2() {
return false;
}
}
结果:
抽象方法1的实现被调用...
钩子方法1被重写...
抽象方法2的实现被调用...
参考文章:
模板模式 | 菜鸟教程
模板方法模式(模板方法设计模式)详解
最后
以上就是稳重胡萝卜为你收集整理的sheng的学习笔记-设计模式-模板模式的全部内容,希望文章能够帮你解决sheng的学习笔记-设计模式-模板模式所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复