• Java策略模式之总有你想不到的知识


    策略模式

    概念

    策略模式(Strategy Pattern)也叫政策模式,是一种比较简单的模式。

    它的目的是定义一组算法,将每个算法都封装起来,并且使它们之间可以互换。

    其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换,使得算法可以在不影响到客户端的情况下发生变化

    策略模式的通用类图如下图所示:
    在这里插入图片描述
    策略模式涉及以下3个角色:

    角色说明
    环境(Context)角色该角色也叫上下文角色,起到承上启下的作用,屏蔽高层模块对策略、算法的直接访问,它持有一个Strategy类的引用。
    抽象策略(Strategy)角色该角色对策略、算法进行抽象,通常定义每个策略或算法必须具有的方法和属性。
    具体策略(Concrete Strategy)角色该角色实现抽象策略中的具体操作,含有具体的算法。

    代码示例

    抽象策略Strategy的代码如下所示:

    package com.shixun.design.strategy;
    
    /**
     * 抽象策略 Strategy类
     */
    public abstract class Strategy {
        public abstract void strategyInterface();
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    具体策略ConcreteStrategy的代码如下所示:

    package com.shixun.design.strategy;
    
    /**
     * 具体策略 ConcreteStrategy 类
     * 实现抽象策略中的具体操作,含有具体的算法
     */
    public class ConcreteStrategy extends Strategy {
        @Override
        public void strategyInterface() {
            System.out.println("呜呼啦呼,实现具体策略!");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    环境角色Context的代码如下所示:

    package com.shixun.design.strategy;
    
    public class Context {
    
        private Strategy strategy = null;
    
        public Context(Strategy strategy) {
            this.strategy = strategy;
        }
    
        public void contextInterface() {
            this.strategy.strategyInterface();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    编写测试代码:

    package com.shixun.design.strategy;
    
    public class Test {
        public static void main(String[] args) {
            Context context = new Context(new ConcreteStrategy());
            context.contextInterface();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    运行结果如下所示:
    在这里插入图片描述

    优缺点

    策略模式优点

    策略模式包括如下优点:

    • 策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族,恰当地使用继承可以把公共的代码移到父类中,从而避免代码重复。
    • 策略模式提供了可以替换继承关系的办法。继承可以处理多种算法或行为,如果不用策略模式,那么使用算法或行为的环境类就可能会有一些子类,每一个子类提供一个不同的算法或行为。但是,这样算法或行为的使用者就和算法本身混在一起,从而不可能再独立演化。
    • 使用策略模式可以避免使用多重条件转移语句。多重转移语句不易维护,它把采取哪一种算法或采取哪一种行为的逻辑与算法或行为的逻辑混合在一起,统统列在一个多重转移语句里面,这比使用继承的办法还要原始和落后。

    策略模式缺点

    策略模式包括如下缺点:

    • 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类,即策略模式只适用于客户端知道所有的算法或行为的情况。
    • 策略模式造成很多的策略类。有时候可以通过把依赖于环境的状态保持到客户端里面,而将策略类设计成可共享的,这样策略类实例可以被不同客户端使用。可以使用享元模式来减少对象的数量。

    应用场景

    策略模式有如下几个应用场景:

    • 多个类只是在算法或行为上稍有不同的场景。
    • 算法需要自由切换的场景。
    • 需要屏蔽算法规则的场景。

    注意事项:如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。

    综合实战:多个算法切换

    定义抽象策略接口

    public interface Strategy {
       public int doOperation(int num1, int num2);
    }
    
    • 1
    • 2
    • 3

    创建实现接口的具体策略类:

    两数加法算法:

    public class OperationAdd implements Strategy{
       @Override
       public int doOperation(int num1, int num2) {
          return num1 + num2;
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    两数减法算法:

    public class OperationSubtract implements Strategy{
       @Override
       public int doOperation(int num1, int num2) {
          return num1 - num2;
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    两数乘法算法:

    public class OperationMultiply implements Strategy{
       @Override
       public int doOperation(int num1, int num2) {
          return num1 * num2;
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    创建 Context 类:

    public class Context {
       private Strategy strategy;
     
       public Context(Strategy strategy){
          this.strategy = strategy;
       }
     
       public int executeStrategy(int num1, int num2){
          return strategy.doOperation(num1, num2);
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    编写测试类:

    public class Test{
       public static void main(String[] args) {
          Context context = new Context(new OperationAdd());    
          System.out.println("10 + 5 = " + context.executeStrategy(10, 5));
     
          context = new Context(new OperationSubtract());      
          System.out.println("10 - 5 = " + context.executeStrategy(10, 5));
     
          context = new Context(new OperationMultiply());    
          System.out.println("10 * 5 = " + context.executeStrategy(10, 5));
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    运行结果:

    10 + 5 = 15
    10 - 5 = 5
    10 * 5 = 50
    
    • 1
    • 2
    • 3
  • 相关阅读:
    5、学习学习MySQL 创建数据库
    c++(五)
    工业级wifi路由器 功能 接口参数
    Spark RDD、DataFrame和Dataset的区别和联系
    vue el-select搜索功能--区分输入内容后得到的是否是下拉框选择数据
    pg_bouncer在使用中的坑勿踩
    Spring之IoC
    C语言——八股文(笔试面试题)
    [论文精读]Graph Attention Networks
    解决ASP.NET Core在Task中使用IServiceProvider的问题
  • 原文地址:https://blog.csdn.net/weixin_45525272/article/details/126302418