设计模式(十六):策略模式(Strategy Pattern)

Published on 2024-04-01 14:28 in 分类: 博客 with 狂盗一枝梅
分类: 博客

一、策略模式定义

策略模式定义比较简单,它的定义如下:

定义一组算法,将每个算法都封装起来,并且使它们之间可以互换(Define a family of algorithms,encapsulate each one,and make them interchangeable.)。

策略模式通用类图如下

策略模式通用类图

按照上面类图,来实现一个简单的代码示例

策略类

public interface Strategy {
    void algorithm();
}

具体策略类

@Slf4j
public class ConcreteStrategyA implements Strategy{
    @Override
    public void algorithm() {
      log.info("ConcreteStrategyA");  
    }
}

@Slf4j
public class ConcreteStrategyB implements Strategy{
    @Override
    public void algorithm() {
        log.info("ConcreteStrategyB");
    }
}

Context类

public class Context {

    private Strategy strategy;

    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    public void algorithm() {
        this.strategy.algorithm();
    }
}

这里的Context类引入Strategy类的方式是通过构造方法的方式,也可以通过Setter的方式,或者直接不使用Strategy成员变量,而是使用Strategy对象作为方法参数传递进来。

启动类

public class Main {
    public static void main(String[] args) {
        Strategy strategy = new ConcreteStrategyA();
        Context context = new Context(strategy);
        context.algorithm();
    }
}

可以看到,策略模式非常简单,没啥好说的,但是没觉得它眼熟吗?

二、策略模式和代理模式

策略模式的重点就是封装角色,它是借用了代理模式的思路,可以想想它和代理模式有什么差别,差别就是策略模式的封装角色和被封装的策略类不用是同一个接口,如果是同一个接口那就成为了代理模式。

代理模式的类图

代理模式通用类图

Proxy类如果没有实现Subject类,那就变成了策略模式。

三、扩展篇:策略枚举

这里借助一个加减法的例子来递进说明下策略枚举:输入三个参数,进行加减法运算参数中两个是int型的,剩下的一个参数是String型的,只有“+”、“-”两个符号可以选择,表示两个参数进行加法或者减法运算,输出运算结果。

方式一:不使用策略模式

非常简单,直接编程实现

public class Calculator {

    //加符号
    private final static String ADD_SYMBOL = "+";
    //减符号
    private final static String SUB_SYMBOL = "-";

    public int exec(int a, int b, String symbol) {
        int result = 0;
        if (symbol.equals(ADD_SYMBOL)) {
            result = this.add(a, b);
        } else if (symbol.equals(SUB_SYMBOL)) {
            result = this.sub(a, b);
        }
        return result;
    }

    //加法运算
    private int add(int a, int b) {
        return a + b;
    }

    //减法运算
    private int sub(int a, int b) {
        return a - b;
    }
}

方式二:使用策略模式

Calculator接口

public interface Calculator {
    int exec(int a, int b);
}

家减法Caculator实现

public class AddCalculator implements Calculator {
    @Override
    public int exec(int a, int b) {
        return a + b;
    }
}

public class SubCalculator implements Calculator {
    @Override
    public int exec(int a, int b) {
        return a - b;
    }
}

Context类

public class Context {

    private Calculator calculator;

    public Context(Calculator calculator) {
        this.calculator = calculator;
    }

    public int exec(int a, int b) {
        return this.calculator.exec(a, b);
    }
}

启动类

public class Main {

    public static void main(String[] args) {

        String ope = "+";
        int a = 1;
        int b = 2;
        Context context = null;
        switch (ope) {
            case "+":
                context = new Context(new AddCalculator());
                break;
            case "-":
                context = new Context(new SubCalculator());
                break;
            default:
                break;
        }
        int exec = context.exec(a, b);
        System.out.println(exec);
    }
}

方式三:策略枚举

来直接看下策略枚举的实现方式

策略枚举类

public enum Calculator {

    //加法
    ADD("+") {
        @Override
        int exec(int a, int b) {
            return a + b;
        }
    },
    SUB("-") {
        @Override
        int exec(int a, int b) {
            return a - b;
        }
    };

    Calculator(String ope) {
        this.ope = ope;
    }

    String ope;

    abstract int exec(int a, int b);

    public static Calculator get(String ope) {
        return Arrays.stream(Calculator.values())
                .filter(item -> item.ope.equals(ope))
                .findFirst()
                .orElse(null);
    }
}

启动类

public class Main {

    public static void main(String[] args) {
        int a = 1;
        int b = 2;
        String ope = "+";
        int result = Calculator.get(ope).exec(a, b);
        System.out.println(result);
    }
}

策略枚举是一个非常优秀和方便的模式,但是它受枚举类型的限制,每个枚举项都是public、final、static的,扩展性受到了一定的约束,因此在系统开发中,策略枚举一般担当不经常发生变化的角色。



END.


#设计模式
目录