一. 场景
假如我们有一个订单业务,根据会员的类型不同,使用if...else
判断,然后去执行不同的业务操作,伪代码如下:
public class OrderService {
public void method(HttpServletRequest req) {
//type:会员类型
String type = req.getParameter("type");
if("free".equals(type)) {
System.out.println("免费用户业务开始。。。");
} else if("normal".equals(type)) {
System.out.println("普通会员业务开始。。。");
} else if("high".equals(type)) {
System.out.println("高级会员业务开始。。。");
} else if("super".equals(type)) {
System.out.println("超级会员业务开始。。。");
} else {
throw new Exception("类型错误.");
}
}
}
根据会员的类型type
,在if...else
判断是免费用户、普通会员、高级会员、超级会员,执行对应的业务操作。
实际业务可能会更多,叠加很多的if...else
,代码看起来很臃肿,不容易维护
二. 优化
策略模式的定义:该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。
设计模式里的策略模式,可以用来优化if...else
和switch...case
多重条件语句的代码
-
抽象业务处理器
public abstract class AbstractHandler { public abstract void handle(); public abstract String type(); }
-
把业务处理器和处理的类型放到一个容器里
@Component public class AbstractHandlerProcessor implements ApplicationContextAware { private ApplicationContext context; private Map<String, AbstractHandler> processorMap = new HashMap<>(); public AbstractHandler choose(String type) { AbstractHandler handler = map.get(type); if(null == handler) { throw new Exception("不支持的type类型,联系管理员。。。") } return handler; } @PostConstruct public void register() { Map<String, AbstractHandler> handlerMap = context.getBeansOfType(AbstractHandler.class); for(AbstractHandler handler : handlerMap.values()) { processorMap.put(handler.type(),handler); } } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.context=applicationContext; } }
PostConstruct
注解会在应用启动时候,加载所有AbstractHandler
类型的处理器,放到AbstractHandlerProcessor
的map
容器中。注意加@Component
注解 -
编写响应的处理器
/** * 免费用户 */ @Component public class FreeHandler extends AbstractHandler { @Override public void handle() { System.out.println("免费用户业务开始。。。"); } @Override public String type() { return "free"; } } /** * 普通会员 */ @Component public class NormalHandler extends AbstractHandler { @Override public void handle() { System.out.println("普通会员业务开始。。。"); } @Override public String type() { return "normal"; } } /** * 高级会员 */ @Component public class HighHandler extends AbstractHandler { @Override public void handle() { System.out.println("高级会员业务开始。。。"); } @Override public String type() { return "high"; } } /** * 超级会员 */ @Component public class SuperHandler extends AbstractHandler { @Override public void handle() { System.out.println("超级会员业务开始。。。"); } @Override public String type() { return "super"; } }
-
测试
@RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(classes=Application.class)// 指定spring-boot的启动类 public class HandlerTest { @Autowired private AbstractHandlerProcessor chooser; @Test public void test() throws Exception{ //准备数据 String type = "free"; //获取任务类型对应的solver AbstractHandlerProcessor processor = chooser.choose(type); //调用不同handle的方法进行处理 processor.handle(); } }
三. 总结
优点
- 多重条件语句不易维护,而使用策略模式可以避免使用多重条件语句,如
if...else
语句、switch...case
语句。 - 符合面向对象的开闭原则,在不修改原来代码的情况下,可以很好的扩展
- 算法的使用放到环境类,算法的实现放到具体的策略类,实现了二者的分离
缺点
- 客户端必须理解所有策略算法的区别,以便适时选择恰当的算法类
- 策略模式造成很多的策略类,增加维护难度
- 增加了学习成本和维护成本