策略模式介绍
策略模式属于Java23种设计模式中的行为型模式。在实际项目开发使用较多。也是面试经常会问到的知识点。
策略模式(strategy pattern)的原始定义是:定义一系列算法,将每一个算法封装起来,并使它们可以相互替换。策略模式让算法可以独立于使用它的客户端而变化。
策略模式的主要角色如下:
抽象策略(Strategy)类:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
具体策略(Concrete Strategy)类:实现了抽象策略定义的接口,提供具体的算法实现或行为。
环境或上下文(Context)类:是使用算法的角色, 持有一个策略类的引用,最终给客户端调用。
该方法委托策略变量调用具体策略所实现的策略接口中的方法(实现接口的类重写策略中的方法,来完成具体功能)
策略模式实现
先看一个简单的实现,快速了解什么是策略模式。
1、定义一个策略接口
public interface Strategy { /** * 执行任务 */ void executeTask();}
2、具体的策略实现,这里实现两个。StrategyA和StrategyB
public class StrategyA implements Strategy { @Override public void executeTask() { System.out.println("执行任务A"); }}
public class StrategyB implements Strategy { @Override public void executeTask() { System.out.println("执行任务B"); }}
3、策略上下文
public class Context { private Strategy strategy; public Context(Strategy strategy) { this.strategy = strategy; } public void executeTask(){ strategy.executeTask(); }}
4、策略调用
@Test public void test001(){ Context context = new Context(new StrategyA()); context.executeTask(); }
相信到这里对策略模式都有了一定的了解,接下来具体看下如果使用策略模式消除if else
策略模式消除if else
1、定义一个实体类
class StrategyModelTest { private String name; private String type;}
2、模拟数据,用于之后策略使用。
public class StrategyList { /** * 用来模拟数据,比如是数据库中查询出来的数据 * @return java.util.List<StrategyModelTest> */ public static List<StrategyModelTest> getList(){ List<StrategyModelTest> strategyModelTestList = new ArrayList<>(); StrategyModelTest strategyModelTestA = new StrategyModelTest(); strategyModelTestA.setName("name"); strategyModelTestA.setType("001"); strategyModelTestList.add(strategyModelTestA); StrategyModelTest strategyModelTestB = new StrategyModelTest(); strategyModelTestB.setName("name"); strategyModelTestB.setType("002"); strategyModelTestList.add(strategyModelTestB); StrategyModelTest strategyModelTestC = new StrategyModelTest(); strategyModelTestC.setName("name"); strategyModelTestC.setType("003"); strategyModelTestList.add(strategyModelTestC);returnstrategyModelTestList; }}
3、策略接口类
public interface StrategyTest { /** * 执行任务 * @author: mkj * @param strategyModelTest */ void executeTask(StrategyModelTest strategyModelTest);}
4、策略实现类,这次实现3个。
public class StrategyTestA implements StrategyTest { @Override public void executeTask(StrategyModelTest strategyModelTest) { System.out.println("执行任务B"+strategyModelTest.getName()); }}public class StrategyTestB implements StrategyTest { @Override public void executeTask(StrategyModelTest strategyModelTest) { System.out.println("执行任务A"+strategyModelTest.getName()); }}public class StrategyTestC implements StrategyTest { @Override public void executeTask(StrategyModelTest strategyModelTest) { System.out.println("执行任务C"+strategyModelTest.getName()); }}
5、策略上下文
public class ContextTest { private StrategyTest strategyTest; public ContextTest(StrategyTest strategyTest) { this.strategyTest = strategyTest; } public void executeTask(StrategyModelTest strategyModelTes){ strategyTest.executeTask(strategyModelTes); }}
6、先看一个反例,使用if else 实现。
可以看见代码里有好几个if else ,这还只是示例,如果在实际开发中,这种逻辑只会更多。
/** * 不使用策略 * @author: mkj */ @Test public void test(){ //这是只是模拟数据,type也可以是当参数传递。List<StrategyModelTest> list = StrategyList.getList(); for (StrategyModelTest strategyModelTest : list){ if ("001".equals(strategyModelTest.getType())){ System.out.println("执行001的业务逻辑"); }else if ("002".equals(strategyModelTest.getType())){ System.out.println("执行002的业务逻辑"); }else { System.out.println("执行003的业务逻辑"); } } }
7、下面看正例。
想要消除if else ,还需要实现一个类,用Map封装策略类。如下:
public class StrategyTestFactory { public StrategyTestFactory() { } /** 使用map来存放策略类,用来消除if else*/ private static Map<String, StrategyTest> strategyMap; public static void init(){ strategyMap = new HashMap<>(8); strategyMap.put("001",new StrategyTestA()); strategyMap.put("002",new StrategyTestB()); strategyMap.put("003",new StrategyTestC()); } public static StrategyTest getStrategy(String type){ return strategyMap.get(type); }}
策略实现:
/** * 使用策略 * @author: mkj */ @Test public void strategyTest(){ List<StrategyModelTest> list = StrategyList.getList(); StrategyTestFactory.init(); for (StrategyModelTest strategyModelTest : list){ StrategyTestFactory.getStrategy(strategyModelTest.getType()).executeTask(strategyModelTest); }}
从示例中可以看出,代码中一个if else 都没有,而且代码更加简洁,也更加利于扩展,如果再有一个不同逻辑,实现一个策略类就可以了,其他代码基本不用动。
策略模式应用场景
1、有多个相似的类,只有行为有差异的情况下,可以考虑使用策略模式。
2、需要在运行时动态切换算法的情况下,可以使用策略模式。
3、一个系统需要在不同时间应用不同的业务规则情况下,可以使用策略模式。
4、在一个系统中,有许多类需要根据某种规则进行排序,查找等操作的情况下,可以使用策略模式。
作者介绍
90年,属马,上班族,怀揣梦想,坚持用心分享,一直想通过自己的努力做出一些成绩。佩服通过自己的坚持实现梦想的人。相信滴水穿石,相信点滴的积累终有一天可以成为自己炫耀的资本!
本篇文章来源于微信公众号: Java技术仓库
微信扫描下方的二维码阅读本文

Comments NOTHING