• 设计模式 | 策略模式(strategy)


    参考: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的时候,可以想起策略模式。让我们的代码可扩展且更易于维护。

  • 相关阅读:
    CKeditor3.6.2 配置与精简
    CKEditor与CKFinder整合并实现文件上传功能
    实体关联关系映射:
    status pending状态
    wx:for
    小程序
    获取指定控件的值
    报表
    dataGridView 设置
    SQLite 的使用
  • 原文地址:https://www.cnblogs.com/imoqian/p/10302940.html
Copyright © 2020-2023  润新知