doclist 阅读(43) 评论(0)
参考:https://www.cnblogs.com/lewis0077/p/5133812.html(深入解析策略模式)

定义:

策略模式定义了一系列的算法,并将每一个算法封装起来,使每个算法可以相互替代,使算法本身和使用算法的客户端分割开来,相互独立。

结构:(书中的图,侵删)

1.一个定义公共方法的接口

2.若干实现了接口的具体实现

3.上下文context,用于跟客户端和策略之间交互

例子:

经过我的思考,我感觉上一篇的简单工厂模式使用的计算器的例子,似乎用在这里更为恰当吧。
我们的目的是选择不同的算法,而不是创建不同的对象。
但其实两者的表现形式很像,只是用途不同。
 
所以,我这里继续用计算器的例子。(书中用的是商户采取不同的优惠策略的例子)

公共接口:

package designpattern.strategy;

public interface Calculate {
    public double calculate(double num1, double num2);
}

具体实现(加减乘除方法):

package designpattern.strategy;

public class Plus implements Calculate {

    @Override
    public double calculate(double num1, double num2) {
        return num1 + num2;
    }

}
package designpattern.strategy;

public class Minus implements Calculate {

    @Override
    public double calculate(double num1, double num2) {
        return num1 - num2;
    }

}
package designpattern.strategy;

public class Multiply implements Calculate {

    @Override
    public double calculate(double num1, double num2) {
        return num1 * num2;
    }

}
package designpattern.strategy;

public class Divide implements Calculate {

    @Override
    public double calculate(double num1, double num2) {
        return num1 / num2;
    }

}

上下文:

package designpattern.strategy;

public class CalculateContext {
    Calculate calculate;

    public CalculateContext(Calculate calculate) {
        super();
        this.calculate = calculate;
    }

    public double calculate(double num1, double num2) {
        return calculate.calculate(num1, num2);
    }
}

客户端:

package designpattern.strategy;

import java.util.Scanner;

public class Calculator {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入一个数字");
        double num1 = scanner.nextDouble();
        System.out.println("请输入一个运算符:+、-、*、/");
        String operator = scanner.next();// 不能用nextLine(),会把上一个回车给吸收
        System.out.println("请输入一个数字");
        double num2 = scanner.nextDouble();

        switch (operator) {
        case "+":
            System.out.println(new CalculateContext(new Plus()).calculate(num1, num2));
            break;
        case "-":
            System.out.println(new CalculateContext(new Minus()).calculate(num1, num2));
            break;
        case "*":
            System.out.println(new CalculateContext(new Multiply()).calculate(num1, num2));
            break;
        case "/":
            System.out.println(new CalculateContext(new Divide()).calculate(num1, num2));
            break;
        default:
            break;
        }

        scanner.close();
    }
}

这样的写法,还是把判断的任务交给了客户端。

可以稍加改善,把判断交给上下文context。

上下文:

package designpattern.strategy;

public class CalculateContext2 {
    Calculate calculate;

    public CalculateContext2(String operate) {
        super();
        switch (operate) {
        case "+":
            this.calculate = new Plus();
            break;
        case "-":
            this.calculate = new Minus();
            break;
        case "*":
            this.calculate = new Multiply();
            break;
        case "/":
            this.calculate = new Divide();
            break;
        }
    }

    public double calculate(double num1, double num2) {
        return calculate.calculate(num1, num2);
    }
}

客户端:

package designpattern.strategy;

import java.util.Scanner;

public class Calculator2 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入一个数字");
        double num1 = scanner.nextDouble();
        System.out.println("请输入一个运算符:+、-、*、/");
        String operator = scanner.next();// 不能用nextLine(),会把上一个回车给吸收
        System.out.println("请输入一个数字");
        double num2 = scanner.nextDouble();

        System.out.println(new CalculateContext2(operator).calculate(num1, num2));

        scanner.close();
    }
}

这里使用了简单工厂模式的思想,传入一个参数,不管具体细节,获得所期望的对象,所以算是简单工厂模式和策略模式的结合。

总结:

策略模式能将我们从if-else中解放出来,当我们需要不停的写if-else的时候,可以想起策略模式。让我们的代码可扩展且更易于维护。