方法一:策略方法實現
1. 抽象策略類:
public interface Operation {
public Integer getResult();
}
具體策略加法類實現:
public classAdd implementsOperation {
private Integer numA;
private Integer numB;
public Add(IntegernumA,Integer numB){
this.numA=numA;
this.numB=numB;
}
@Override
public Integer getResult() {
// TODO Auto-generated method stub
return numA+numB;
}
public Integer getNumA() {
return numA;
}
public void setNumA(Integer numA) {
this.numA = numA;
}
public Integer getNumB() {
return numB;
}
public void setNumB(Integer numB) {
this.numB = numB;
}
}
具體策略減法類實現:
public classSub implementsOperation {
private Integer numA;
private Integer numB;
public Sub(IntegernumA,Integer numB){
this.numA=numA;
this.numB=numB;
}
@Override
public Integer getResult() {
// TODO Auto-generated method stub
return numA-numB;
}
public void setNumA(Integer numA) {
this.numA = numA;
}
public Integer getNumB() {
return numB;
}
public void setNumB(Integer numB) {
this.numB = numB;
}
}
2. 上下文類
public classOperationContext {
Operationoper;
publicOperationContext(Operation oper){
this.oper=oper;
}
public Integer getResult(){
return oper.getResult();
}
}
3. 客戶端實現
public staticvoidmain(String[] args) {
// TODO Auto-generated method stub
Integerresult=0;
System.out.print("請輸入第一個數字:");
Scannerin=newScanner(System.in);
StringnumA=in.nextLine();
System.out.print("請輸入第二個數字:");
in=new Scanner(System.in);
StringnumB=in.nextLine();
System.out.print("請輸入要進行的運算:");
in=new Scanner(System.in);
Stringopration=in.nextLine();
if(opration.equals("+")){
result=new OperationContext(new Add(Integer.parseInt(numA),Integer.parseInt(numB))).getResult();
System.out.println(result);
}
if(opration.equals("-")){
result=new OperationContext(new Sub(Integer.parseInt(numA),Integer.parseInt(numB))).getResult();
System.out.println(result);
}
}
}
從客戶端類可以看出弊端,需要在客戶類test裏面判斷使用哪一個算法(類Add還是類Sub),OperationContext給人的感覺就是具體操作的一個代理而已。初看貌似還不如前一篇文章中的簡單工廠方法的實現。
方法二:策略與簡單工廠結合
1、上下文類:
public classOperationContext2 {
Operationoper;
publicOperationContext2(String oper,Integer numA,Integer numB){
switch(oper){
case "+":
this.oper=new Add(numA,numB);break;
case "-":
this.oper=new Sub(numA,numB);break;
}
}
public Integer getResult(){
return oper.getResult();
}
}
2、客戶端實現:
public classtest2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Integerresult=0;
System.out.print("請輸入第一個數字:");
Scannerin=newScanner(System.in);
StringnumA=in.nextLine();
System.out.print("請輸入第二個數字:");
in=new Scanner(System.in);
StringnumB=in.nextLine();
System.out.print("請輸入要進行的運算:");
in=new Scanner(System.in);
Stringoperation=in.nextLine();
result=newOperationContext2(operation,Integer.parseInt(numA),Integer.parseInt(numB)).getResult();
System.out.println(result);
}
}
從客戶端代碼result=newOperationContext2(operation,Integer.parseInt(numA),Integer.parseInt(numB)).getResult();
可以知道,此時客戶端只需認識類OperationContext2就可以實現計算操作,而簡單工廠模式則需要認識兩個類,Operation類和OperationFactory類。因此耦合度更低了。
總結:
策略模式定義了一系列的算法,並將每一個算法封裝起來,而且使它們還可以相互替換。策略模式讓算法獨立於使用它的客戶而獨立變化。
1、 優點
1) 策略模式提供了管理相關的算法族的辦法。策略類的等級結構定義了一個算法或行爲族。恰當使用繼承可以把公共的代碼轉移到父類裏面,從而避免重複的代碼。
2) 策略模式提供了可以替換繼承關係的辦法。繼承可以處理多種算法或行爲。如果不是用策略模式,那麼使用算法或行爲的環境類就可能會有一些子類,每一個子類提供一個不同的算法或行爲。但是,這樣一來算法或行爲的使用者就和算法或行爲本身混在一起。決定使用哪一種算法或採取哪一種行爲的邏輯就和算法或行爲的邏輯混合在一起,從而不可能再獨立演化。繼承使得動態改變算法或行爲變得不可能。
3) 使用策略模式可以避免使用多重條件轉移語句。多重轉移語句不易維護,它把採取哪一種算法或採取哪一種行爲的邏輯與算法或行爲的邏輯混合在一起,統統列在一個多重轉移語句裏面,比使用繼承的辦法還要原始和落後。
2、 缺點
1) 客戶端必須知道所有的策略類,並自行決定使用哪一個策略類。這就意味着客戶端必須理解這些算法的區別,以便適時選擇恰當的算法類。換言之,策略模式只適用於客戶端知道所有的算法或行爲的情況。
2) 策略模式造成很多的策略類,每個具體策略類都會產生一個新類。有時候可以通過把依賴於環境的狀態保存到客戶端裏面,而將策略類設計成可共享的,這樣策略類實例可以被不同客戶端使用。換言之,可以使用享元模式來減少對象的數量。
3、 應用場景
1) 多個類只區別在表現行爲不同,可以使用Strategy模式,在運行時動態選擇具體要執行的行爲。
2) 需要在不同情況下使用不同的策略(算法),或者策略還可能在未來用其它方式來實現。
3) 對客戶隱藏具體策略(算法)的實現細節,彼此完全獨立。