設計模式 - 模板方法模式 (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

留言

這個網誌中的熱門文章

Java Lambda Map篇

(InterviewBit) System Design - Design Cache System

設計模式 - 享元模式 (Structural Patterns - Flyweight Design Pattern)