策略模式介绍

策略模式属于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、定义一个实体类

@Datapublic 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技术仓库



微信扫描下方的二维码阅读本文

此作者没有提供个人介绍
最后更新于 2024-05-24