十一黃金週,對於像咱們這些屌絲來講,確實是個不錯的出遊時機,惋惜的就是這個假期是public的,並非我等屌絲獨佔的。真是有種生前活在人堆裏的感慨,這時候選擇交通工具是異常的重要,筆者回家須要通過深汕高速,每逢節假日,高速基本都會成爲免費停車場的,加之國慶免費,真是雪上加霜啊。今天我所寫的就是以選擇交通工具爲題闡述一下策略模式吧。java
1. 定義:定義一組算法,將每一個算法都封裝起來,並使他們之間能夠互換。算法
2. 類圖:【以下圖所示】設計模式
3. 類圖說明:ide
3.1 ITransport:策略抽象類,定義每一個算法必須具備的方法和屬性。 工具
3.2 Plane,Train,Car:策略中一組算法。this
3.3 Context:上下文角色,封裝算法提供客戶端調用的。 spa
1. 策略抽象類設計
package com.pattern.stratgy.core; /** * 策略接口——交通工具 * @author yemaoan * */ public interface ITransport { void buyTicket(); }
2. 具體策略(算法)code
2.1 選擇火車對象
package com.pattern.stratgy.core; public class Train implements ITransport { @Override public void buyTicket() { System.out.println("選擇坐火車,硬座還比較划算"); } }
2.2 選擇飛機
package com.pattern.stratgy.core; public class Plane implements ITransport { @Override public void buyTicket() { System.out.println("選擇坐飛機吧,快速,便捷,關鍵啊,是不會塞車..."); } }
2.3 選擇汽車
package com.pattern.stratgy.core; public class Car implements ITransport { @Override public void buyTicket() { System.out.println("選擇坐汽車,堵就堵吧"); } }
3. Context封裝角色
package com.pattern.stratgy.core; /** * 封裝角色 * @author yemaoan * */ public class Context { private ITransport transport; public Context(ITransport transport) { this.transport = transport; } public void buyTicket() { this.transport.buyTicket(); } }
4. JunitTest
package com.pattern.strategy.test; import org.junit.Test; import com.pattern.stratgy.core.Context; import com.pattern.stratgy.core.ITransport; import com.pattern.stratgy.core.Train; public class TestStrategy { @Test public void testStrage() { //生平就差火車,動車沒坐過了,讓我也過一下火車癮吧 ITransport transport = new Train(); //生成策略對象,這樣Client就知道得太多了,不該該啊,這是病,得醫~ Context context = new Context(transport); context.buyTicket(); } }
其實單純的策略模式的弊病已經在上面的代碼中表現得很明顯了,在客戶端調用時已經把當前的策略暴露出去了,怎麼解決?讓工廠幫一下忙吧,讓咱們看一下下面的一段代碼。
1. 策略工廠
package com.pattern.stategy.factory; import com.pattern.stratgy.core.ITransport; /** * 設計模式老朋友了——策略工廠類 * @author yemaoan * */ public class StrategyFactory { public static <T extends ITransport> T getTransport(Class<T> cls) { ITransport transport = null; try { transport = (ITransport) Class.forName(cls.getName()).newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return (T) transport; } public static <T extends ITransport> T getTransport(String code) { return (T) getTransport(new ContentService().get(code)); } }
2. 算法值映射類
package com.pattern.stategy.factory; import java.util.HashMap; import java.util.Map; import com.pattern.stratgy.core.Car; import com.pattern.stratgy.core.Plane; import com.pattern.stratgy.core.Train; /** * 算法映射 * @author yemaoan * */ public class ContentService { private Map<String, Class> contentMap = new HashMap<String, Class>(); public ContentService() { contentMap.put("train", Train.class); contentMap.put("plane", Plane.class); contentMap.put("car", Car.class); } public Class get(String key) { return contentMap.get(key); } }
3. JunitTest【Client】
package com.pattern.strategy.test; import org.junit.Test; import com.pattern.stategy.factory.StrategyFactory; import com.pattern.stratgy.core.Context; import com.pattern.stratgy.core.ITransport; import com.pattern.stratgy.core.Train; public class TestStrategy { @Test public void testStrage() { //生平就差火車,動車沒坐過了,讓我也過一下火車癮吧 ITransport transport = new Train(); //生成策略對象,這樣Client就知道得太多了,不該該啊,這是病,得醫~ Context context = new Context(transport); context.buyTicket(); } @Test public void testStrategy() { ITransport transport = StrategyFactory.getTransport("train"); //讓工廠模式幫了我一把 Context context = new Context(transport); context.buyTicket(); } }
1. 本文是對策略模式的一個闡述,策略其實也算是一個比較好理解的模式吧。固然單純的使用策略模式是不太現實的,由於它會把算法徹底的暴露給調用者,兵家之大忌啊。
2. 針對策略模式的一些不足,筆者採用了工廠模式去解決,使得客戶端調用時,只須要根據特定的code來獲取相應的算法策略,而避免直接new算法策略。