一长串if / else / execute代码分支的最佳设计模式/方法
我有一个“遗留”代码,我想重构。
代码基本上是对服务器进行远程调用并获得回复。 然后根据回复执行相应的。
代码骨架示例:
public Object processResponse(String responseType, Object response) { if(responseType.equals(CLIENT_REGISTERED)) { //code //code ... } else if (responseType.equals(CLIENT_ABORTED)) { //code //code.... } else if (responseType.equals(DATA_SPLIT)) { //code //code... } etc
问题是有很多if / else分支,并且每个内部的代码都不是微不足道的。
因此很难维护。
我想知道这个最好的模式是什么?
我有一个想法是创建一个方法名称与responseType相同的单个对象,然后在processResponse内部使用reflection调用与responseType同名的方法。
这将清理processResponse,但它会将代码移动到具有许多/多种方法的单个对象,我认为reflection会导致性能问题。
是否有一个很好的设计方法/模式来清理它?
两种方法:
- 战略模式http://www.dofactory.com/javascript/strategy-design-pattern
- 创建字典,其中key是元数据(在您的情况下元数据是responseType),value是函数。
例如:
把它放在构造函数中
responses = new HashMap
其中ImplementationForRegisteredClient
和ImplementationForAbortedClient
实现SomeAbstraction
并通过responses.get(responseType).MethodOfYourAbstraction(SomeParams);
调用此字典responses.get(responseType).MethodOfYourAbstraction(SomeParams);
如果您想遵循DI原则,可以在客户端类中注入此Dictionary。
我的第一个切割是用switch / case替换if / else if结构:
public Object processResponse(String responseType, Object response) { switch(responseType) { case CLIENT_REGISTERED: { //code ... } case CLIENT_ABORTED: { //code.... } case DATA_SPLIT: { //code... }
从那里我可能会提取每个块作为一种方法,并从那里应用策略模式。 在任何感觉正确的地方停下来。
您描述的案例似乎完全适合策略模式的应用。 特别是,您有许多算法变体,即根据远程服务器调用的响应执行的代码。
实现Stategy模式意味着您必须定义一个类层次结构,如下所示:
public interface ResponseProcessor { public void execute(Context ctx); } class ClientRegistered implements ResponseProcessor { public void execute(Context ctx) { // Actions corresponding to a client that is registered // ... } } class ClientAborted implements ResponseProcessor { public void execute(Context ctx) { // Actions corresponding to a client aborted // ... } } // and so on...
Context
类型应包含执行每个“策略”所需的所有信息。 请注意,如果不同的策略共享一些算法片段,您也可以使用其中的Templeate方法模式 。
您需要工厂在运行时创建特定策略。 工厂将根据收到的回复制定战略。 可能的实现应该是@Sattar Imamov建议的实现。 工厂将包含if .. else
代码。
如果策略类不需要构建,并且在构建时不需要任何外部信息,您还可以将每个策略映射到Enumeration的值。
public enum ResponseType { CLIENT_REGISTERED(new ClientRegistered()), CLIENT_ABORTED(new ClientAborted()), DATA_SPLIT(new DataSplit()); // Processor associated to a response private ResponseProcessor processor; private ResponseType(ResponseProcessor processor) { this.processor = processor; } public ResponseProcessor getProcessor() { return this.processor; } }