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可以帶來什麼改變。
0 意見:
張貼留言