Java設計模式(九)
------------策略模式
定義
定義一組策略算法,將每個算法都封裝起來,並且使它們之間可以互換。策略模式使這些算法在客戶端調用它們的時候能夠互不影響地變化。
實例
比如一級方程式中的賽車的輪胎,可以使用雨胎,幹胎,中性胎;一個Swing 容器可以設定佈局管理器,可以是FlowLayout,BorderLayout…;他們都可以動態相互替換,這些都是典型的策略模式。
用法概述
策略模式(Strategy)屬於對象行爲型設計模式,主要是定義一系列的策略算法,把這些算
法一個個封裝成擁有共同接口的單獨的類,並且使它們之間可以互換。策略模式使這些算法
在客戶端調用它們的時候能夠互不影響地變化。這裏的算法不要狹義的理解爲數據結構中算
法,可以理解爲不同的業務處理方法。
這種做法會帶來什麼樣的好處呢?
它將算法的使用和算法本身分離,即將變化的具體算法封裝了起來,降低了代碼的耦合
度,系統業務策略的更變僅需少量修改。算法被提取出來,這樣可以使算法得到重用。
構造
我們延續上面Swing佈局管理器的例子,我們這裏就模擬一下它的實現,如果感興趣可以參看JDK的源碼。
角色
算法使用環境(Context)角色
通常是一個抽象實體和一組實現子類,在抽象類中定義一個抽象策略的引用,執行這個策略一般以方法的形式定義再在抽象類父中(因爲父類並不關心使用的是什麼策略),如果有默認策略我們應該在父類中進行指定。
public abstract class AbstractContainer { public String name = ""; // 所有容器都具有的show功能 public abstract void show(); public LayoutStrategy layout;
public LayoutStrategy getLayout() { return layout; }
public void setLayout(LayoutStrategy layout) { this.layout = layout; }
public void doLayout() { if (layout == null) { layout = new BorderLayout(); } layout.layout(); }
}
|
public class MyFrame extends AbstractContainer { @Override public void show() { // TODO Auto-generated method stub layout = new BorderLayout(); this.doLayout(); System.out.println("我是一個自定義窗口"); } }
|
public class MyPanel extends AbstractContainer { @Override public void show() { // TODO Auto-generated method stub //layout=new FlowLayout(); //this.setLayout(layout); this.doLayout(); System.out.println("我是一個自定義面板"); } } |
抽象策略(Strategy)角色
public interface LayoutStrategy { public void layout();
} |
具體策略(Concrete Strategy)角色:
public class BorderLayout implements LayoutStrategy {
@Override public void layout() { // TODO Auto-generated method stub System.out.println("我使用了BorderLayout佈局管理器"); }
}
public class FlowLayout implements LayoutStrategy {
@Override public void layout() { // TODO Auto-generated method stub System.out.println("我使用了FlowLayout佈局管理器"); } } |
客戶端代碼:
public class MyTest { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub AbstractContainer panel=new MyPanel(); panel.show();
AbstractContainer frame =new MyFrame(); frame.show();
//動態改變策略 panel.setLayout(new FlowLayout()); panel.show(); } }
打印結果: 我使用了BorderLayout佈局管理器 我是一個自定義面板 我使用了BorderLayout佈局管理器 我是一個自定義窗口 我使用了FlowLayout佈局管理器 我是一個自定義面板 |
總結
下面是使用策略模式的一些建議:
1) 系統需要能夠在幾種算法中快速的切換。
2) 系統中有一些類它們僅某些行爲策略不同時(通常爲擁有同一個父類的子類),可以考慮採用策略模式來進行重構。
3) 系統中存在多重條件選擇語句時,可以考慮採用策略模式來重構。
但是要注意一點,策略模式中不可以同時使用多於一個的策略算法。
我們爲什麼要使用策略模式,用繼承不行嗎?
繼承的缺點:
1.代碼在多個子類中重複
2.運行時的行爲不容易改變
3.改變會牽一髮動全身,造成其他子類不想要的改變。
策略模式優點:
1.方便增加新的處理方式(策略)
2.應付客戶改變需求,對於某應用需要採用新的方式,比如改變數據庫