|
考慮您要設計一個更換各種符號的工具類TextCharChange,您是否會採用這樣的方式: public void replace() {
switch(getChangeType()) { case RN_TYPE: replaceRN(); break; case N_TYPE: replaceN(); break; case OTHER_TYPE: replaceOTHER(): break; ... } } 這麼作的缺點是,日後您要增加更換符號的策略時,會有幾個地方需要修改:增加TYPE常數、增加TextCharChange中的 replaceXXX()方法、增加 replace()方法中的switch case判斷。 像這種策略採用的情況,可以將策略加以封裝為一個物件,而不是將策略寫死在某個類中,如此一來,策略可以獨立於客戶端,隨時增加變化、增加或減少策略,即使是修改每個策略的內容,也不會對客戶端程式造成影響。 來舉個最簡單的例子,首先要知道Windows與Linux的文字檔案換行符號是不同的,Windows是 /r/n ,而Linux是 /n,今天您要設計一個文字編輯器,在適當的時候,您必須要能隨時轉換這兩種符號,如果不採用上面的策略採用流程的話,要如何設計:
public abstract class TextStrategy {
public class LinuxStrategy extends TextStrategy {
public class WindowsStrategy extends TextStrategy {
public class TextCharChange {
public class Main {
為了明顯的秀出結果,我們使用@n來表示 '/n' , @r 表示 '/r' 符號,Main中的流程是個假設的情況,何時採用何種策略是隨機的。 在Strategy模式中,使用一個公開的介面replace(),讓客戶端請求,而在實作replace()時,可以任意的組合演算策略,程式中的 preOperation()、postOperation()就是用以示意演算的組合概念,Strategy模式封裝了這些演算過程,使它們易於組合、 修改、替換,上面這個例子的UML 類別結構圖如下所示: ![]() Strategy模式的UML類別結構圖如下: ![]() State模式:看當前是什麼狀態,就採取什麼動作。 Strategy模式:看需求(情境)是什麼,採用適當的策略。 不過兩者雖相似,應用的場合稍有不同,State模式中有一個重點在於設定狀態變化,就像 Gof 例子中舉的TCP連線;Strategy策略模式則是直接採用適當的策略的感覺,例如Gof中說的,採用適當的演算法來作正文換行。 在Java SE中Strategy的實例是GUI中,Container與LayoutManager的關係,Container對其所包納的元件該如何排列,是依所給定的LayoutManager而定(例如BorderLayout、FlowLayout)。 |