设计模式之策略者模式

147 阅读3分钟

1.简介

策略模式(Strategy Pattern)属于对象的行为模式。 其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。 策略模式使得算法可以在不影响到客户端的情况下发生变化。其主要目的是通过定义相似的算法,替换if else 语句写法,并且可以随时相互替换。

2.UML图

策略模式UML.png

3.代码实现

* 这里为了方便理解,我们就拿刚学习Java的时候使用计算方法来说吧。
* 在使用计算器进行计算的时候,会经常用到加减乘除方法。如果我们想得到两个数字相加的和,我们需要用到“+”符号,得到相减的差,需要用到“-”符号等等。
* 虽然我们可以通过字符串比较使用if/else写成通用方法,但是计算的符号每次增加,我们就不得不加在原先的方法中进行增加相应的代码,
* 如果后续计算方法增加、修改或删除,那么会使后续的维护变得困难。
* 但是在这些方法中,我们发现其基本方法是固定的,这时我们就可以通过策略模式来进行开发,
* 可以有效避免通过if/else来进行判断,即使后续增加其他的计算规则也可灵活进行调整。

首先定义一个抽象策略角色,并拥有一个计算的方法。

package com.gs.designmodel.strategymodel.operation;
​
/**
 * @author: Gaos
 * @Date: 2022-11-23 16:22
 *
 **/
public interface CalculateStrategy {
​
    /**
     * 做操作
     * @param num1
     * @param num2
     * @return
     */
    int doOperation(int num1, int num2);
}
​

然后再定义加减乘除这些具体策略角色并实现方法。

package com.gs.designmodel.strategymodel.operation;
​
/**
 * @author: Gaos
 * @Date: 2022-11-23 16:24
 *
 * 然后再定义加减乘除这些具体策略角色并实现方法。
 **/
public class OperationAdd implements CalculateStrategy{
​
    @Override
    public int doOperation(int num1, int num2) {
        return num1 + num2;
    }
}
package com.gs.designmodel.strategymodel.operation;
​
/**
 * @author: Gaos
 * @Date: 2022-11-23 16:40
 **/
public class OperationDiv implements CalculateStrategy{
    @Override
    public int doOperation(int num1, int num2) {
        return num1 / num2;
    }
}
package com.gs.designmodel.strategymodel.operation;
​
/**
 * @author: Gaos
 * @Date: 2022-11-23 16:40
 **/
public class OperationMul implements CalculateStrategy{
    @Override
    public int doOperation(int num1, int num2) {
        return num1 * num2;
    }
}
package com.gs.designmodel.strategymodel.operation;
​
/**
 * @author: Gaos
 * @Date: 2022-11-23 16:39
 **/
public class OperationSub implements CalculateStrategy{
    @Override
    public int doOperation(int num1, int num2) {
        return num1 - num2;
    }
}

最后在定义一个环境角色,提供一个计算的接口供客户端使用。

package com.gs.designmodel.strategymodel.operation;
​
/**
 * @author: Gaos
 * @Date: 2022-11-23 16:41
 *  最后在定义一个环境角色,提供一个计算的接口供客户端使用。
 **/
public class CalculatorContext {
    private CalculateStrategy calculateStrategy;
​
    public CalculatorContext(CalculateStrategy calculateStrategy) {
        this.calculateStrategy = calculateStrategy;
    }
​
    public int executeStrategy(int num1, int num2) {
        return calculateStrategy.doOperation(num1, num2);
    }
}

测试:

    // 测试
    public static void main(String[] args) {
        int a=4,b=2;
        // 这边其实也可以与简易工厂模式相结合
        CalculatorContext context = new CalculatorContext(new OperationAdd());
        System.out.println("a + b = "+context.executeStrategy(a, b));
​
        CalculatorContext context2 = new CalculatorContext(new OperationSub());
        System.out.println("a - b = "+context2.executeStrategy(a, b));
​
        CalculatorContext context3 = new CalculatorContext(new OperationMul());
        System.out.println("a * b = "+context3.executeStrategy(a, b));
​
        CalculatorContext context4 = new CalculatorContext(new OperationDiv());
        System.out.println("a / b = "+context4.executeStrategy(a, b));
    }

结果: 策略模式结果.png

4.总结

策略模式主要用来分离算法,根据相同行为抽象来做不同的策略的具体实现。例如上面例子中不管是加减乘除的哪种策略都具有计算这一相同行为。

策略模式结构清晰明了,使用简单直观。并且耦合度相对而言较低,利于扩展,同时操作封装也更为彻底,数据更加安全。

但是它的缺点也十分明显,就是随着策略的增加,子类也会变得繁多。

虽然常常被用来说目的是为了替换掉 if..else, 但其实应该根据其特点,及其他模式的组合拥有更多的实现,不应该拘泥于这一个目的。