[設計模式] Strategy Pattern(策略模式) Part 1

策略模式在Head First Design Pattern這本書中,是最先被介紹到的設計模式,可見得他應該是很重要且很基本的模式之一。以下就讓我們來記錄學習的心得並且分享筆記給大家。策略模式的基本定義如下:

Define a family of algorithms, encapsulate each one, and make them interchangeable. [The] Strategy [pattern] lets the algorithm vary independently from clients that use it.

【中文版】策略模式在於觀察程式中變動的部分,並且將他們抽離出來封裝成可互相抽換的演算法家族。這個模式讓你即使任意更換實作的演算法,也不會變動到去使用者他們的客戶端程式。

在這篇文章中,我們先看看如果不使用策略模式時,撰寫出來的程式是如何,接著在下一篇文章中進行一個對比。

讓我們考量一個情境(此情境延伸自Head First Design Pattern的練習),假設我們需要設計一組遊戲角色,我們可能會先定義一個角色類別,每一個遊戲角色都可以攻擊(fight)、行動(action)和交談(chat):


public abstract class Character {
    public abstract void fight();
    public abstract void action();
    public abstract void char();
}

這是一個很簡單的角色類別,加上abstract修飾子,讓繼承Character的class必須強迫去實作fight、walk和talk這三個方法。接著就可以真正創造我們的角色,假設我們有國王(King)、皇后(Queen)和騎士(Knight)這三個角色,那我們會這樣定義三個類別:

public class King extends Character {

     @Override
     public void action() {
         System.out.println("King walk");
     }

     @Override
     public void chat() {
         System.out.println("King chat");
     }

     @Override
     public void fight() {
          System.out.println("King fight by hand");
     }
}



public class Queen extends Character {

     @Override
     public void action() {
         System.out.println("Queen walk");
     }

     @Override
     public void chat() {
         System.out.println("Queen chat");
     }

     @Override
     public void fight() {
          System.out.println("Queen fight by hand");
}



public class Knight extends Character {

     @Override
     public void action() {
         System.out.println("Knight walk");
     }

     @Override
     public void chat() {
         System.out.println("Knight chat");
     }

     @Override
     public void fight() {
          System.out.println("Knight fight by hand");
}

角色都創建好了,看起來好像都沒有問題,但假設某天我們的遊戲改版了,使用者可以購買武器來殺敵,我們需要擴充程式來滿足這樣的需求。所以老闆說需要增加【寶劍】、【斧頭】、【匕首】等三種不同的新的攻擊模式,慘了,我們需要在角色類別裡面增加三個方法:


public abstract void fightBySword();
public abstract void fightByKnife();
public abstract void fightByAxe();


但是,問題來了,所有繼承角色這個類別的子類別都必須要實作這三個方法,但是假設皇后不能用斧頭只能用匕首、國王只能用寶劍...,這樣一來就很麻煩,我們必須要在個別角色裡面新增這三個方法,然後有些方法是空的...,多麼不好的寫法!

所以,利用繼承是會有缺點的,改變父類別的內容會連帶的更動到所有繼承他的子類別。在下一篇中我們來看看Strategy Pattern可以帶來什麼改變。

Share this post!

Bookmark and Share

0 意見: