- 一文帶你搞懂Java動態代理
- 幾分鐘帶你搞懂策略模式
- 幾分鐘帶你搞懂觀察者模式
- 一文徹底搞明白工廠和抽象工廠
- 一文搞明白裝飾者模式
- 最全單例模式
- 幾段代碼搞明白命令模式
- 幾段代碼搞明白適配器模式
- 一看就懂的外觀模式
- 一看就懂的模版方法模式
- 幾段代碼搞懂迭代器模式
- 一文搞懂明白狀態模式
小張:週五xx公園團建,安排見下,望周知:
- 9:00 集合
- 9:00-11:00 登山
- 11:00-13:00 山頂集合,午餐
領導:小張啊,你規劃幾條上山路線,扔到羣裏。
小張:自己查去,收到。
(十分鐘後,微信羣…)
小張:時間較緊,大家請自行合理安排上山路線
- 上山路程最短,較陡,xx->xx
- 適合拍照,景色美,xx->xx
- 山路好走,xx->xx
策略模式
關於策略模式的定義,我就直接引用HeadFirst書中的描述了:策略模式定義了算法蔟,並分別封裝起來,讓它們之間可以互相替換,此模式讓算法的變化獨立於使用算法的客戶。類圖見下:
我們用代碼語言來描述下,爲什麼要使用接口,而不是直接使用具體的路線類?因爲我們不應該把每個員工與具體的上山路線綁在一起,員工在登山時有權利改變路線(動態綁定),而當員工持有一個抽象上山路線類時,我們就可以在運行時動態的引用正確的具體上山路線類型(多態思想),所以我們應該針對接口編程,不針對實現編程。
/**
* 這是上山路線的接口
*/
public interface IStrategyRoutes {
// 上山路線信息
void mcRoutesInfo();
}
這是爲員工提供的路線A,路程最短。登山路線的不同,這也是這個需求(集合-登山-午餐)每個員工變化的部分,我們之所以把每種具體的上山路線都單獨的封裝起來,而不是將方法一個個的添加到各自員工類內部,是因爲考慮到代碼的複用,符合封裝變化的OO原則
public class ShortestWalkRoutes implements IStrategyRoutes {
@Override
public void mcRoutesInfo() {
System.out.println("上山路程最短");
}
}
這是爲員工提供的路線B,適合拍照,景色美:
public class CameraRoutes implements IStrategyRoutes {
@Override
public void mcRoutesInfo() {
System.out.println("適合拍照,景色美");
}
}
這是爲員工提供的路線C,山路好走:
public class EasyRoadRoutes implements IStrategyRoutes {
@Override
public void mcRoutesInfo() {
System.out.println("山路好走");
}
}
同樣我們可以將每個員工的共性抽離出來。在StaffBase類中加入接口類型變量(而不是具體的上山路線),每個員工都會動態的設置這個變量意在運行時引用正確的行爲類型(例如:步行最少、適合拍照等),所以我們應該針對接口編程,而非針對實現編程。
/**
* 這是一個員工類的基類
*/
public abstract class StaffBase {
IStrategyRoutes routes;
public void setRoutes(IStrategyRoutes routes){
this.routes = routes;
}
// 針對接口編程,而不是具體實現,這樣我們就不會把特定路線和特定員工死死的綁定在一起
public void showStaffRoutes(){
routes.trafficRoutesInfo();
}
// 將當前員工名字打印出來
public abstract void showName();
}
登山時,員工可以選擇適合自己的上山路線,如員工李四。這裏採用靜態工廠方法,讓員工的代碼與路線對象創建代碼解耦。添加其他員工,我們只需要添加新類並繼承StaffBase基類即可,不需要更改其他代碼,符合對擴展開放,對修改關閉原則。
public class StaffOne extends StaffBase {
public StaffOne(){
// 員工李四默認選擇了步行最少的路線
// 此處之所以沒有直接new主要是不想讓員工和路線綁的死死的
routes = RoutesFactory.getRoutes(1);
}
@Override
public void showName() {
System.out.print("本人李四");
}
}
這是一個簡單的靜態工廠,目的是產生一些上山路線的對象。
public class RoutesFactory {
public static IStrategyRoutes getRoutes(int type) {
IStrategyRoutes routes;
switch (type) {
case 1:
// 步行最少
routes = new ShortestWalkRoutes();
break;
case 2:
// 適合拍照,景色美
routes = new CameraRoutes();
break;
case 3:
// 容易好走
routes = new EasyRoadRoutes();
break;
default:
// 默認安全第一
routes = new EasyRoadRoutes();
break;
}
return routes;
}
}
最後來個測試類吧,StaffOne 來採用距離最短方案上山。
public class StrategyPatternTest {
public static void main(String[] args) {
StaffBase staff1 = new StaffOne();
staff1.showName();
staff1.showStaffRoutes();
}
}
再回頭來看下策略模式的定義:我們定義了算法蔟,並分別封裝起來,讓它們之間可以互相替換,此模式讓算法的變化獨立於使用算法的客戶。在本例中,上山具有不同的路線方案,都能達到到達山頂的目的,我們可稱其爲策略,而具體的路線策略變更對於員工無影響,員工只需知道選擇方案1 可最短距離,具體的路線安排是A-B-C-D也好,A-C-B-D也罷,員工在登山之前並不關心。