設計模式(一)帶你搞懂策略模式

小張:週五xx公園團建,安排見下,望周知:

  1. 9:00 集合
  2. 9:00-11:00 登山
  3. 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也罷,員工在登山之前並不關心。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章