模板模式
在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。
**主要解决:**一些方法通用,却在每一个子类都重新写了这一方法。
注意:
-
父类必须是抽象类
-
模板方法或者叫公共逻辑方法必须用final修饰 ,如:play()
保证其不会被子类修改
-
子方法必须是抽象,如endPlay()
-
可以添加一个protect 表明其需要在子类中实现
因为protect可以在同一个类,同一个包,不同包的子类也可以访问到
public abstract class Game {
abstract void initialize();
//可以添加一个protect 表明其需要在子类中实现
//protected abstract void initialize();
abstract void startPlay();
abstract void endPlay();
//模板,即公共逻辑
public final void play(){
//初始化游戏
initialize();
//开始游戏
startPlay();
//结束游戏
endPlay();
}
}
子类
package moshi.moban;
public class BasBall extends Game {
@Override
void initialize() {
System.out.println("BasBall start ");
}
@Override
void startPlay() {
System.out.println("BasBall start ");
}
@Override
void endPlay() {
System.out.println("BasBall start ");
}
}
package moshi.moban;
public class Football extends Game {
@Override
void initialize() {
System.out.println("football init ");
}
@Override
void startPlay() {
System.out.println("football start ");
}
@Override
void endPlay() {
System.out.println("football end ");
}
public static void main(String[] args) {
Game football =new Football();
football.play();
System.out.println();
football=new BasBall();
football.play();
}
}
结果:
football init
football start
football end
BasBall start
BasBall start
BasBall start
其实,模板模式中还有一个钩子方法的概念,有人称,具有钩子方法的模板模式才算完整,也许吧。
钩子方法时干啥的呢?钩子就是给子类一个授权,允许子类通过重写钩子方法来颠覆基本逻辑的执行,这有时候是非常有用的。就比如在盖房子的时候,有一个需要子类来决定是否建造厕所间的需求时,可以这么实现:
public abstract class HouseTemplate {
protected HouseTemplate(String name){
this.name = name;
}
protected String name;
protected abstract void buildDoor();
protected abstract void buildWindow();
protected abstract void buildWall();
protected abstract void buildBase();
protected abstract void buildToilet();
//钩子方法
protected boolean isBuildToilet(){
return true;
}
//公共逻辑
public final void buildHouse(){
buildBase();
buildWall();
buildDoor();
buildWindow();
if(isBuildToilet()){
buildToilet();
}
}
}
子类一:要实现建厕所
public class HouseOne extends HouseTemplate {
HouseOne(String name){
super(name);
}
HouseOne(String name, boolean isBuildToilet){
this(name);
this.isBuildToilet = isBuildToilet;
}
public boolean isBuildToilet;
@Override
protected void buildDoor() {
System.out.println(name +"的门要采用防盗门");
}
@Override
protected void buildWindow() {
System.out.println(name + "的窗户要面向北方");
}
@Override
protected void buildWall() {
System.out.println(name + "的墙使用大理石建造");
}
@Override
protected void buildBase() {
System.out.println(name + "的地基使用钢铁地基");
}
@Override
protected void buildToilet() {
System.out.println(name + "的厕所建在东南角");
}
@Override
protected boolean isBuildToilet(){
return isBuildToilet;
}
}
子类二:不要要建厕所
public class HouseTwo extends HouseTemplate {
HouseTwo(String name){
super(name);
}
@Override
protected void buildDoor() {
System.out.println(name + "的门采用木门");
}
@Override
protected void buildWindow() {
System.out.println(name + "的窗户要向南");
}
@Override
protected void buildWall() {
System.out.println(name + "的墙使用玻璃制造");
}
@Override
protected void buildBase() {
System.out.println(name + "的地基使用花岗岩");
}
@Override
protected void buildToilet() {
System.out.println(name + "的厕所建在西北角");
}
}
测试类
public class Clienter {
public static void main(String[] args){
HouseTemplate houseOne = new HouseOne("房子1", false);
HouseTemplate houseTwo = new HouseTwo("房子2");
houseOne.buildHouse();
houseTwo.buildHouse();
}
}
结果:
房子1的地基使用钢铁地基
房子1的墙使用大理石建造
房子1的门要采用防盗门
房子1的窗户要面向北方
房子2的地基使用花岗岩
房子2的墙使用玻璃制造
房子2的门采用木门
房子2的窗户要向南
房子2的厕所建在西北角
执行结果