欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

设计模式 | 策略模式

程序员文章站 2022-05-17 14:48:35
参考:https://www.cnblogs.com/lewis0077/p/5133812.html(深入解析策略模式) 参考: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的时候,可以想起策略模式。让我们的代码可扩展且更易于维护。