策略 – 通过接口types自动注册

我有很多的行动。 所有的动作都和一些在所有动作中传递的Object / Context一起工作。 我想使用模式策略/政策。

这里是Kotlin的例子:

interface Action { val name: String fun run(ctx: Context) } class Multiply: Action { override name = "MULTIPLY" override fun run(ctx: Context) { writeToDb(ctx.id, ctx.number * 2) } } class Substract class SendNotification etc... 

所以我想在启动时注册所有策略。 从Enum这样的结构中选择策略。

 val action = selectAwaitingAction() val ctx = selectCtxById(action.transaction_id) perfromAction(ctx, actions.getByName(action.name)) fun performAction(ctx Context, action: Action) { action.run(ctx) } 

我的问题是如何通过接口types注册策略?

注意:这是完整的例子。 如果仅查看通过接口types进行自动注册,请滚动至答案的最后部分。

策略设计模式可以使用function表来实现。 这将实现存储在Map ,其中key是算法的名称,value是算法的具体实现。

常用方法:

考虑一下class Context所有在接口Solver之间共享的参数。

 public class Context extends HashMap { public  T get(String key, Class resultClass){ return resultClass.cast(get(key)); } public  T getOrDefault(String key, T def, Class resultClass){ return resultClass.cast(getOrDefault(key,def)); } } 

并且用所需的方法solvename界面Solver

 public interface Solver { void solve(Context context); String name(); } 

然后,您可以创建Solver接口修改共享Context对象的实现。 在这个例子中我创建了AddSolverMultiplySolver

AddSolver.java:

 public class AddSolver implements Solver { @Override public void solve(Context context) { context.put("result", context.getOrDefault("result",0.0, Double.class) + context.get("add", Double.class)); } @Override public String name() { return "+"; } } 

MultiplySolver.java

 public class MultiplySolver implements Solver { @Override public void solve(Context context) { context.put("result", context.getOrDefault("result",0.0, Double.class) * context.get("multiply", Double.class)); } @Override public String name() { return "*"; } } 

手动构建Map

接口Solver实现可以存储在HashMap

 @Test public void testCustomFunctionMap(){ HashMap functionMap = new HashMap<>(); functionMap.put("+", new AddSolver()); functionMap.put("*", new MultiplySolver()); Context context = new Context(); context.put("add", 2.0); functionMap.get("+").solve(context); TestCase.assertEquals(2.0, context.get("result", Double.class)); context.put("multiply", 3.0); functionMap.get("*").solve(context); TestCase.assertEquals(6.0, context.get("result", Double.class)); } 

自动构建Map

有更多的方法,如果你需要自动构造Map 。 这个问题中提到了很多。 我已经使用了org.reflections库。

 public class SolverScanner{ static HashMap functionMap; static { functionMap = new HashMap<>(); Reflections reflections = new Reflections(SolverScanner.class.getPackage().getName()); for( Class clazz : reflections.getSubTypesOf(Solver.class)){ try { Solver solver = clazz.newInstance(); functionMap.put(solver.name(), solver); } catch (Exception e) { throw new IllegalStateException("Cannot construct functionMap",e); } } } public static HashMap getFunctionMap(){ return functionMap; } private SolverScanner(){}//disable instantiating } 

和用法:

 @Test public void testSolverScannerFunctionMap(){ HashMap functionMap = SolverScanner.getFunctionMap(); Context context = new Context(); context.put("add", 2.0); functionMap.get("+").solve(context); TestCase.assertEquals(2.0, context.get("result", Double.class)); context.put("multiply", 3.0); functionMap.get("*").solve(context); TestCase.assertEquals(6.0, context.get("result", Double.class)); }