一、基本概念:
1、定义:
在父类中定义算法的框架(方法),将部分实现延迟到子类中,让子类可以重新定义算法中的某些步骤(复写某些方法)。
2、类图:
- AbstractClass表示抽象模块,内部方法一般分为基本方法和模板方法两种。基本方法在父类中无具体实现(抽象方法),需要在子类进行相关实现。模块方法是定义在父类中,完成对模板方法的调用。
- 两个子类是具体模板,负责对基本方法的具体实现
3、使用场景:
- 多个子类有公有方法,调用逻辑相似
- 相同逻辑抽取到父类中,子类通过钩子函数约束父类的行为。
二、具体使用:
1、抽象模板-游戏模板
public abstract class Game {
//基本方法
//初始化
abstract void initialize();
//开始游戏
abstract void startPlay();
//游戏结束
abstract void endPlay();
//模板方法
private void play(){
initialize();
startPlay();
endPlay();
}
}
复制代码
2、具体模板:
(1)LOL:
public class LoLGame extends Game {
@Override
void initialize() {
System.out.println("英雄升级");
}
@Override
void startPlay() {
System.out.println("开始团战");
}
@Override
void endPlay() {
System.out.println("团战胜利");
}
}
复制代码
(2)吃鸡:
public class ChiJiGame extends Game {
@Override
void initialize() {
System.out.println("捡抢捡装备");
}
@Override
void startPlay() {
System.out.println("猥琐进圈");
}
@Override
void endPlay() {
System.out.println("胜利吃鸡");
}
}
复制代码
三、钩子方法的使用:
通过子类对父类的行为进行控制
1、抽象模板:
public abstract class Game {
//基本方法
//初始化
abstract void initialize();
abstract void startPlay();
abstract void endPlay();
//钩子方法
// 投降
boolean isSurrender(){
return false;
}
//模板方法
public void play(){
initialize();
if (!isSurrender()){
startPlay();
}
endPlay();
}
}
复制代码
2、具体模板:
public class LoLGame extends Game {
@Override
void initialize() {
System.out.println("英雄升级升技能");
}
@Override
void startPlay() {
System.out.println("开始团战");
}
@Override
void endPlay() {
System.out.println("团战胜利");
}
@Override
boolean isSurrender() {
return true;
}
}
复制代码
子类可以通过控制父类钩子方法的返回值的类型去改变父类的调用逻辑
四、View中的模板方法
View中事件分发、UI绘制都用到了模板方法
1、View
public class View implements Drawable.Callback, KeyEvent.Callback,
AccessibilityEventSource {
......
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
}
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
}
protected void onDraw(Canvas canvas) {
}
}
复制代码
在onMeasure方法有具体实现,onLayout、onDraw则是由子类进行实现
2、LinearLayout
public class LinearLayout extends ViewGroup {
......
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (mOrientation == VERTICAL) {
measureVertical(widthMeasureSpec, heightMeasureSpec);
} else {
measureHorizontal(widthMeasureSpec, heightMeasureSpec);
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (mOrientation == VERTICAL) {
layoutVertical(l, t, r, b);
} else {
layoutHorizontal(l, t, r, b);
}
}
@Override
protected void onDraw(Canvas canvas) {
if (mDivider == null) {
return;
}
if (mOrientation == VERTICAL) {
drawDividersVertical(canvas);
} else {
drawDividersHorizontal(canvas);
}
}
......
}
复制代码
在LinearLayout中,根据mOrientation的不同,进行不同的实现。