1. 概述 策略模式(Strategy Pattern )作为一种软件设计模式,用来实现对象的某个行为,该行为在不同的场景中拥有不同的实现逻辑。它定义了一组算法,同时将这些算法封装起来,并使它们之间可以互换。
常用的策略模式有如下三个角色:
抽象策略角色 — Strategy 抽象策略类,通常为一个接口,其中定义了某个策略行为【即策略算法标识】。
具体策略角色 — ConcreteStrategy 具体策略类,实现抽象策略中的策略行为;每一个具体策略类即代表一种策略算法。
上下文角色 — Context 上下文类,起承上启下封装作用,屏蔽高层模块对策略、算法的直接访问,封装可能存在的变化。
本篇在上述常用的策略模式基础上,结合门面模式和调整后的策略上下文,构建了一套通用策略模式实现。
下面我们用这套通用策略模式来模拟一下各种动物的喊叫行为:
2. 参考 flea-common使用之通用策略模式实现 源代码
3. 实现 3.1 定义Flea策略接口类 IFleaStrategy 定义了通用的策略行为,T 类型表示 Flea 策略执行结果对应的类型,P 类型表示 Flea 策略上下文参数。 具体代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public interface IFleaStrategy <T, P> { T execute (final P contextParam) throws FleaStrategyException; }
3.2 定义狗喊叫声策略类 DogVoiceStrategy 用于定义狗喊叫声策略,返回 "阿狗【" + name + "】正在喊叫着;汪汪汪"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class DogVoiceStrategy implements IFleaStrategy <String, String> { @Override public String execute (String name) throws FleaStrategyException { return "阿狗【" + name + "】正在喊叫着;汪汪汪" ; } }
3.3 定义猫喊叫声策略类 CatVoiceStrategy 用于定义猫喊叫声策略,返回 "阿猫【" + name + "】正在喊叫着;喵喵喵"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class CatVoiceStrategy implements IFleaStrategy <String, String> { @Override public String execute (String name) throws FleaStrategyException { return "阿猫【" + name + "】正在喊叫着;喵喵喵" ; } }
3.4 定义鸭喊叫声策略类 DuckVoiceStrategy 定义鸭喊叫声策略,返回 "阿鸭【" + name + "】正在喊叫着;嘎嘎嘎"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class DuckVoiceStrategy implements IFleaStrategy <String, String> { @Override public String execute (String name) throws FleaStrategyException { return "阿鸭【" + name + "】正在喊叫着;嘎嘎嘎" ; } }
3.5 定义策略上下文接口类 IFleaStrategyContext 策略上下文接口,定义统一的策略上下文调用方法,同时可通过 getContext 获取上下文参数,setContext 设置上下文参数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 public interface IFleaStrategyContext <T, P> { T invoke (String strategy) throws FleaStrategyException; void setContext (P contextParam) ; P getContext () ; }
3.6 定义Flea抽象策略上下文类 FleaStrategyContext Flea 抽象策略上下文类,封装了策略执行的逻辑,对外屏蔽高层模块对策略的直接访问。抽象方法 init 用于初始化 Flea 策略实现 Map ,该方法由Flea 策略抽象上下文的子类实现,并在策略上下文子类实例化时,调用该方法完成具体初始化的工作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 public abstract class FleaStrategyContext <T, P> implements IFleaStrategyContext <T, P> { private Map<String, IFleaStrategy<T, P>> fleaStrategyMap; private P contextParam; public FleaStrategyContext () { fleaStrategyMap = init(); } public FleaStrategyContext (P contextParam) { this (); this .contextParam = contextParam; } protected abstract Map<String, IFleaStrategy<T, P>> init () ; @Override public T invoke (String strategy) throws FleaStrategyException { if (ObjectUtils.isEmpty(fleaStrategyMap)) { throw new FleaStrategyException ("The Strategy Map is not initialized!" ); } IFleaStrategy<T, P> fleaStrategy = fleaStrategyMap.get(strategy); if (ObjectUtils.isEmpty(fleaStrategy)) { throw new FleaStrategyNotFoundException ("The Strategy [name =\"" + strategy + "\"] is not found!" ); } return fleaStrategy.execute(contextParam); } @Override public void setContext (P contextParam) { this .contextParam = contextParam; } @Override public P getContext () { return contextParam; } }
3.7 定义动物喊叫声策略上下文类 AnimalVoiceContext 动物喊叫声策略上下文,继承 Flea 抽象策略上下文,实现 init 方法,用于初始化 Flea 策略实现 Map ,其中 key 为 策略名,value 为 具体的动物喊叫声策略实现类;Collections.unmodifiableMap 用于返回一个 只读 的 Map 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 public class AnimalVoiceContext extends FleaStrategyContext <String, String> { private static Map<String, IFleaStrategy<String, String>> fleaStrategyMap; static { fleaStrategyMap = new HashMap <>(); fleaStrategyMap.put("dog" , new DogVoiceStrategy ()); fleaStrategyMap.put("cat" , new CatVoiceStrategy ()); fleaStrategyMap.put("duck" , new DuckVoiceStrategy ()); fleaStrategyMap = Collections.unmodifiableMap(fleaStrategyMap); } public AnimalVoiceContext () { } public AnimalVoiceContext (String contextParam) { super (contextParam); } @Override protected Map<String, IFleaStrategy<String, String>> init () { return fleaStrategyMap; } }
3.8 定义Flea策略门面 FleaStrategyFacade 定义 Flea 策略调用的统一入口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public class FleaStrategyFacade { private FleaStrategyFacade () { } public static <T, P> T invoke (String strategy, IFleaStrategyContext<T, P> fleaStrategyContext) throws FleaStrategyException { return fleaStrategyContext.invoke(strategy); } }
4. 测试 单元自测类可查看 FleaStrategyTest 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public class FleaStrategyTest { private static final FleaLogger LOGGER = FleaLoggerProxy.getProxyInstance(FleaStrategyTest.class); @Test public void testStrategy () { AnimalVoiceContext context = new AnimalVoiceContext ("旺财" ); LOGGER.debug(FleaStrategyFacade.invoke("dog" , context)); context.setContext("Tom" ); LOGGER.debug(FleaStrategyFacade.invoke("cat" , context)); AnimalVoiceContext context1 = new AnimalVoiceContext (); context1.setContext("Donald" ); LOGGER.debug(FleaStrategyFacade.invoke("duck" , context1)); } }
单元测试类运行结果如下:
总结 好了,通用策略模式模式实现–Flea Strategy
已讲解完毕,欢迎大家使用 !