設計模式 - 模板方法模式 (Behavioral Patterns - Template Method Design Pattern)
前言
Template Pattern就像是之前談過的Builder Pattern和Strategy Pattern混合版本,這個Pattern主要在
- 定義一個演算法流程介面,讓不同的實作圍繞著介面的方法去繁衍出不同的演算法
- 而這些流程都稱為一個佔位(佔住一個流程的位子),為何稱為佔位,我們舉個例子,今天如果我們要做英雄攻擊動畫,而這個程式設計我們可以很簡單的就叫做Attack,但是問題來了不同的英雄攻擊動作不一樣,所以我們必須將這個攻擊拆分成不同的細節(攻擊方法包含-舉手、前進、揮砍、收起武器),而這些動作就可以稱為placeholders(我自稱佔位QQ),讓整個演算法的粒度變小,可以透過class繼承的方式去修改這些粒度
和Strategy與Builder相比
- 和Strategy相比,策略模式的意象聚焦於不同演算法的切換(沒有佔位切分粒度的概念)-我個人私心認為如果策略模式要變得更複雜的話也是一種Template模式
- 和Builder相比Builder也是讓Client分不同步驟去呼叫Object,但是他的目的是創建一個物件,而Template Method更聚焦於執行一個流程
類別圖
實踐方法
- 定義出你的演算法方法介面 (攻擊演算法-舉手、揮砍、收刀)
- 根據不同的實作具演化你的每個演算法佔位(placeholder或細節)流程
範例
- 定義出英雄攻擊的Template Method介面 (不一定是interface,在此用default作為共用方法)
- 不同類型的攻擊繼承此模板方法
interface AttackMethod {
default void attack() {
pickUpWeapon();
moveForward();
hitEnemy();
putDownWeapon();
};
void pickUpWeapon();
void moveForward();
void hitEnemy();
void putDownWeapon();
}
class MagicianAttack implements AttackMethod {
@Override
public void pickUpWeapon() {
System.out.println("Pick up a stick");
}
@Override
public void moveForward() {
System.out.println("Move slowly");
}
@Override
public void hitEnemy() {
System.out.println("Use stick to hit the enemy");
}
@Override
public void putDownWeapon() {
System.out.println("Put down the stick");
}
}
class WarriorAttack implements AttackMethod {
@Override
public void pickUpWeapon() {
System.out.println("Pick up a sword");
}
@Override
public void moveForward() {
System.out.println("Move slowly");
}
@Override
public void hitEnemy() {
System.out.println("Use sword to hit the enemy");
}
@Override
public void putDownWeapon() {
System.out.println("Put down the sword");
}
}
class Hero {
public void attack(AttackMethod attackMethod) {
attackMethod.attack();
}
}
public class Template {
public static void main(String[] args) {
AttackMethod magicianAttack = new MagicianAttack();
AttackMethod warriorAttack = new WarriorAttack();
Hero hero = new Hero();
hero.attack(magicianAttack);
hero.attack(warriorAttack);
}
}
結論
- 如果有比較複雜但是流程一至,而且想保持可以隨時抽換的演算法時,可以考慮使用template method
留言
張貼留言