一, 回顧簡單工廠模式(SimpleFactory)
上一篇博文: http://blog.csdn.net/nvd11/article/details/41855937
還是用回那個計算器作例子.
用簡單工廠模式實現的UML圖是這樣的:
客戶端關鍵代碼:
private void BtnClicked_btnDel(){
int i = Integer.parseInt(tb_i.getText());
int j = Integer.parseInt(tb_j.getText());
Operation oper = OperationFactory.getOperationObj(i,j,"-");
lblResult.setText("" + oper.getResult());
}
可見, 使用簡單工廠後, 在客戶端只知道算法是Operation的子類實現的, 但是不知道具體是哪個子類(OperationAdd 還是 OperationDel).
也就是將真正的業務子類對客戶端隱藏了.
正專業的講法就是把業務類封裝起來.
但是, 在上面的例子中, 即使使用了簡單工廠模式把業務類封裝起來, 但是還是暴露了真正的算法(方法)名字 GetResult().
二,策略模式(Strategy)定義
所謂策略模式其實跟簡單工廠模式在定義上有點類似, 只不過簡單工廠封裝的是業務類, 而策略模式封裝了方法(算法),
也就講令客戶端無法知道真正的業務方法名字.
再簡單點講,
就是利用面向對象多態, 根據子類的不同而調用不同的重寫方法.
對於上面計算器的例子.
我們移除OperationFactory類, 類似地, 添加1個叫做OperationContext的類, 它的作用有點類似與工廠類OperationFactory
Factory類: 工廠, 具有1個靜態方法. 根據參數的不同返回不同的類的對象. 通常不實例化工廠類, 只調用其靜態方法生成對象.
Context類: 具有非靜態1個方法, 根據參數對象的不同調用相同(重寫自同一超類)的方法. 客戶端通常會實例化這個類.
上所提到的對象所屬的類都是繼承(或間接繼承)自同1個超類.
三,具體代碼
3.1 Operation 類
跟上次的例子變化不大, 加上了Set方法.
public abstract class Operation {
private int i;
private int j;
public int getI(){
return i;
}
public void setI(int i){
this.i = i;
}
public void setJ(int j){
this.j = j;
}
public int getJ(){
return j;
}
public abstract int getResult();
}
3.2 OperationAdd 類
public class OperationAdd extends Operation{
@Override
public int getResult(){
return this.getI() + this.getJ();
}
}
3.3 OperationDel 類
public class OperationDel extends Operation{
@Override
public int getResult(){
return this.getI() - this.getJ();
}
}
3.3 OperationContext 類
public class OperationContext {
private Operation oper;
public OperationContext(Operation oper){
this.oper = oper;
}
public int compute(int i, int j){
oper.setI(i);
oper.setJ(j);
return oper.getResult();
}
}
可見它可以根據oper對象的不同, 而調用不同的同名方法, 這就是多態的基本特性!
3.5 客戶端代碼
private void BtnClicked_btnDel(){
int i = Integer.parseInt(tb_i.getText());
int j = Integer.parseInt(tb_j.getText());
Operation oper = new OperationDel();
OperationContext context = new OperationContext(oper);
lblResult.setText("" + context.compute(i,j));
}
3.6 UML
四, 策略模式和簡單工廠模式相結合
策略模式對客戶端封裝(隱藏)了 業務的具體方法, 也就是說上面例子中的客戶端調用OperationContext類的compute方法來計算, 而不知道真正的方法是getResutl().
但是上面的客戶端暴露了OperationDel類...
而簡單工廠模式的好處就是可以封裝具體業務類.
所以將兩個模式結合就可以同時封裝業務類和業務方法(算法).
簡單修改下OperationContext:
package strategy.bizobj;
public class OperationContext {
private Operation oper;
public OperationContext(Operation oper){
this.oper = oper;
}
//Simple Factory
public OperationContext(String symbol){
switch(symbol){
case "+": this.oper = new OperationAdd();
case "-": this.oper = new OperationDel();
}
}
public int compute(int i, int j){
oper.setI(i);
oper.setJ(j);
return oper.getResult();
}
}
上面的Context類就是簡單工廠模式和策略模式的集合了.
此時的客戶端代碼:
private void BtnClicked_btnDel(){
int i = Integer.parseInt(tb_i.getText());
int j = Integer.parseInt(tb_j.getText());
OperationContext context = new OperationContext("-");
lblResult.setText("" + context.compute(i,j));
}
相當簡潔, 同時隱藏(封裝)了業務類和業務方法.
擴展性同樣很強大, 如果需要增加乘法button, 只需要增加1個乘法類, 以及修改簡單工廠內的switch 代碼.