定義
定義一組算法,將每個算法都封裝起來,並且使它們之間可以互換。【維基百科】
起源
在一個系統中,針對同一種行爲,需要針對不同的情況有各自具體的實現,這時,如果不採用一種比較好的設計模式的話,會出現許多if…else(if)語句,爲了避免這種情況的發生,於是就有了策略模式。
類圖
說明:
- Stategy 策略,也就是上文提到的行爲
- ConcreteStrategy 具體的策略角色,即每一種行爲的具體實現
- Context 角色,要去執行這些行爲的對象,在這個類中,會將抽象的行爲注入進去,即Stategy,在執行行爲的時候,會根據具體的子類對象去執行對應的行爲。
case
員工每天早上去上班,不同的人,上班的時間點和採用的交通方式也不一樣,住的遠的人,7點就要出發了,坐公交或者自駕,住的近的人,可能7點30分纔出發,騎自行車或者電動車,如果在沒有使用策略模式之前,代碼是這樣實現的:
package com.steven.cn.simple;
public class Test1 {
/**
* 枚舉,爲了測試方便
* @author Steven
*
*/
private enum Type {
FAR("FAR", "住的遠的人"), NEAR("NEAR", "住的近的人");
private String value;
private String valueName;
private Type(String value, String valueName) {
this.value = value;
this.valueName = valueName;
}
}
/**
* 行爲
* @param type
*/
public static void goCompany(String type) {
if(Type.FAR.value.equals(type)) {
System.out.println("每天7點鐘從家出發,坐公交或者自駕");
}else if(Type.NEAR.value.equals(type)) {
System.out.println("每天7點30分從家出發,騎自行車或者電動車");
}
}
public static void main(String[] args) {
goCompany(Type.FAR.value);
}
}
如果採用策略模式的話,會變成下面這種方式:
首先會有一個抽象的行爲類,一般是採用接口,可以多實現
package com.steven.cn.stategy;
/**
* 策略類
* @author Steven
*
*/
public interface IStategy {
public void goCompany();
}
行爲的具體實現,因爲有不同的實現方式,所以會有多個類
package com.steven.cn.stategy.impl;
import com.steven.cn.stategy.IStategy;
/**
* 住的遠的人的行爲實現類
* @author Steven
*
*/
public class ConcreteStrategyA implements IStategy{
@Override
public void goCompany() {
System.out.println("每天7點鐘從家出發,坐公交或者自駕");
}
}
package com.steven.cn.stategy.impl;
import com.steven.cn.stategy.IStategy;
/**
* 住的近的人的行爲實現類
* @author Steven
*
*/
public class ConcreteStrategyB implements IStategy{
@Override
public void goCompany() {
System.out.println("每天7點30分從家出發,騎自行車或者電動車");
}
}
最後會有一個角色類,這個類會決定行爲的具體實現方式
package com.steven.cn.context;
import com.steven.cn.stategy.IStategy;
public class Employee {
private IStategy stategy;
public Employee(IStategy stategy) {
this.stategy = stategy;
}
public IStategy getStategy() {
return stategy;
}
// 這裏提供set方法,是爲了多一種方式封裝角色,可以只使用構造方法來封裝角色。
public void setStategy(IStategy stategy) {
this.stategy = stategy;
}
public void execGoCompany() {
stategy.goCompany();
}
}
測試類
package com.steven.cn;
import com.steven.cn.context.Employee;
import com.steven.cn.stategy.impl.ConcreteStrategyA;
import com.steven.cn.stategy.impl.ConcreteStrategyB;
public class Test {
public static void main(String[] args) {
Employee employee;
// 住的遠的人
employee = new Employee(new ConcreteStrategyA());
employee.execGoCompany();
System.out.println("--------------");
// 住的近的人
employee = new Employee(new ConcreteStrategyB());
employee.execGoCompany();
System.out.println("--------------");
employee.setStategy(new ConcreteStrategyA());
employee.execGoCompany();
System.out.println("--------------");
}
}
最後的輸出結果是
結果自己運行一下就知道了。。。
END
通過上面兩種情況下代碼的對比,優缺點很明顯了
優點:
- 避免使用繁雜的if...else(if)語句進行判斷
- 行爲的具體實現方式可以自由的切換,通過封裝不同的角色就可以實現不同的行爲
- 擴展性高,增加一種行爲的實現方式,只需要實現接口即可
缺點
- 類增多了,每添加一個行爲的具體實現,就多出一個類出來
- 所有的實現方式都必須告訴別人,這樣別人才能決定使用哪個策略角色
源碼下載地址:源碼下載地址