• 设计模式-策略模式


    1.什么是策略模式

    策略模式(Strategy Pattern)也叫做政策模式(Policy Pattern)这种类型的设计模式属于行为型模式
    定义一组 算法,将每个算法都封装起来,并且使它们之间可以互换。

    自己的理解 做事情 不同情况的处理

    引入<<设计模式之禅>>中的例子  刘备江东娶妻 赵云使用诸葛亮三条锦囊妙计

    例子1

    public class StrategyPattern {
    
        static class ZhaoYun {
            //赵云出场了,他根据诸葛亮给他的交代,依次拆开妙计
            public static void main(String[] args) {
                Context context;
                System.out.println("---拆第一个---");
                context = new Context(new BackDoor());
                context.operate();
    
                System.out.println("---拆第二个了---");
                context = new Context(new GivenGreenLight());
                context.operate();
    
                System.out.println("---拆第三个---");
                context = new Context(new BlockEnemy());
                context.operate();
            }
        }
    
        /**
         * 妙计  策略接口
         */
        interface IStrategy {
            public void operate();
        }
    
        /**
         * 找乔国老走后门  具体策略类  策略接口子类
         */
         static class BackDoor implements IStrategy {
            @Override
            public void operate() {
                System.out.println("找乔国老帮忙,让吴国太给孙权施加压力");
            }
        }
    
        /**
         * 求吴国太开绿灯 具体策略类  策略接口子类
         */
        static class GivenGreenLight implements IStrategy {
            @Override
            public void operate() {
                System.out.println("求吴国太开绿灯,放行!");
            }
        }
    
        /**
         * 孙夫人断后 具体策略类  策略接口子类
         */
        static class BlockEnemy implements IStrategy {
            @Override
            public void operate() {
                System.out.println("孙夫人断后,挡住追兵");
            }
        }
    
        /**
         * 锦囊  环境类  策略执行入口
         */
        static class Context {
            private IStrategy straegy;
    
            public Context(IStrategy strategy) {
                this.straegy = strategy;
            }
    
            public void operate() {
                this.straegy.operate();
            }
        }
    }
    View Code

    结果如下

    调用不同策略就对不同情况进行处理

    做事情会有很多情况  不同情况会有不同的处理

    比如说想要去旅行  那么旅行要选择那种交通方式呢  飞机 高铁 火车 自家 都行

    例子2

    public class StrategyPattern2 {
        
        public static void main(String[] args) {
        //模拟客户端调用 选择不同策略 使用不同的旅行方式
        GoTravel airplane = new GoTravel(new Airplane());
        System.out.println("旅行方式" + airplane.tool());
    
        GoTravel car = new GoTravel(new Car());
        System.out.println("旅行方式" + car.tool());
    
        GoTravel highTrain = new GoTravel(new HignTrain());
        System.out.println("旅行方式" + highTrain.tool());
    }
    
    
        /**
         *  策略接口  想去旅行
         */
        interface Travel {
            public String tool();
        }
    
        /***
         *   环境类    具体执行策略入口
         */
        static class GoTravel {
    
            private Travel travel;
    
            public GoTravel(Travel travel) {
                this.travel = travel;
            }
    
            public String tool() {
                return travel.tool();
            }
        }
    
        /***
         *   具体策略类   策略接口子类
         */
        static class Car implements Travel {
            @Override
            public String tool() {
                return "开车";
            }
        }
    
        /***
         *   具体策略类   策略接口子类
         */
        static class HignTrain implements Travel {
            @Override
            public String tool() {
                return "坐高铁";
            }
        }
    
        /***
         *   具体策略类   策略接口子类
         */
        static class Airplane implements Travel {
            @Override
            public String tool() {
                return "坐飞机";
            }
        }
    }
    View Code

    结果如下

    2.为什么要用策略模式

    使用了策略模式 

    1.减少大量的if-else语句,可自动切换不同的实现

    2.扩展性强   添加策略即添加具体策略实现类

    商家对不同客户会执行不同价格 新用户 老用户 VIP用户

    例子3

    public class PriceManagement {
    
        public static void main(String[] args) {
            BigDecimal price = getPrice(new BigDecimal("10"), "新客户");
            System.out.println("price = " + price);
            BigDecimal price2 = getPrice(new BigDecimal("10"), "老客户");
            System.out.println("price2 = " + price2);
            BigDecimal price3 = getPrice(new BigDecimal("10"), "VIP客户");
            System.out.println("price3 = " + price3);
        }
    
        public static BigDecimal getPrice(BigDecimal price , String customType){
            if ("新客户".equals(customType)) {
                System.out.println("抱歉!新客户没有折扣!");
                return price;
            }else if ("老客户".equals(customType)) {
                System.out.println("恭喜你!老客户打9折!");
                price = price.multiply(new BigDecimal("0.9"))
                             .setScale(2,BigDecimal.ROUND_HALF_UP);
                return price;
            }else if("VIP客户".equals(customType)){
                System.out.println("恭喜你!VIP客户打8折!");
                price = price.multiply(new BigDecimal("0.8"))
                             .setScale(2,BigDecimal.ROUND_HALF_UP);
                return price;
            }
            //其他人员都是原价
            return price;
        }
    }
    View Code

    结果如下

    问题 1  

    getPrice方法  对于不同用户执行不同的方法 可以抽离出来

    修改例子3 如下

    public class PriceManagementImprove {
    
        public static void main(String[] args) {
            BigDecimal price = getPrice(new BigDecimal("10"), "新客户");
            System.out.println("price = " + price);
            BigDecimal price2 = getPrice(new BigDecimal("10"), "老客户");
            System.out.println("price2 = " + price2);
            BigDecimal price3 = getPrice(new BigDecimal("10"), "VIP客户");
            System.out.println("price3 = " + price3);
        }
        
        public static BigDecimal getPrice(BigDecimal price, String customType){
            if ("新客户".equals(customType)) {
                return checkNewCustomer(price);
            }else if ("老客户".equals(customType)) {
                return checkOldCustomer(price);
            }else if("VIP客户".equals(customType)){
                return checkVIPCustomer(price);
            }
            //其他人员都是原价
            return price;
        }
    
        /**
         * 对VIP客户的报价算法
         * @param price 原价
         * @return 折后价
         */
        private static BigDecimal checkVIPCustomer(BigDecimal price) {
            System.out.println("恭喜!VIP客户打8折");
            price = price.multiply(new BigDecimal(0.8))
                         .setScale(2,BigDecimal.ROUND_HALF_UP);
            return price;
        }
    
        /**
         * 对老客户的报价算法
         * @param price 原价
         * @return 折后价
         */
        private static BigDecimal checkOldCustomer(BigDecimal price) {
            System.out.println("恭喜!老客户打9折");
            price = price.multiply(new BigDecimal(0.9))
                         .setScale(2,BigDecimal.ROUND_HALF_UP);
            return price;
        }
    
        /**
         * 对新客户的报价算法
         * @param price 原价
         * @return 折后价
         */
        private static BigDecimal checkNewCustomer(BigDecimal price) {
            System.out.println("抱歉!新客户没有折扣!");
            return price;
        }
    }
    View Code

    结果如下

    问题 2 

    代码仍然有if..else多分支判断  如果价格情况更多 就需要更多else分支

    修改例子3 如下 使用策略模式 并增加新的MVP客户

    public class StrategyPattern3 {
        public static void main(String[] args) {
                    //1.创建老客户的价格策略
                    PriceStrategy oldStrategy = new OldCustomerStrategy();
    
                    //2.创建环境类,并设置具体的报价策略
                    PriceContext context = new PriceContext(oldStrategy);
    
                    //3.调用环境类的方法
                    BigDecimal price = context.getPrice(new BigDecimal(100));
    
                    System.out.println("折扣价为:" +price);
    
    
                    //新增MVP
                    PriceStrategy mvpStrategy = new MVPCustomerStrategy();
                    PriceContext mvpContext = new PriceContext(mvpStrategy);
                    BigDecimal mvpPrice = mvpContext.getPrice(new BigDecimal(100));
                    System.out.println("MVP折扣价为:" +mvpPrice);
    
    
        }
    
        /**
         * 策略接口   价格策略
         */
        interface PriceStrategy {
            BigDecimal getPrice(BigDecimal price);
        }
    
    
        /***
         *   环境类    具体执行策略入口
         */
         static class PriceContext {
            //持有一个具体的价格策略
            private PriceStrategy priceStrategy;
    
            //注入价格策略
            public PriceContext(PriceStrategy priceStrategy){
                this.priceStrategy = priceStrategy;
            }
    
            //回调具体价格策略的方法
            public BigDecimal getPrice(BigDecimal price){
                return priceStrategy.getPrice(price);
            }
        }
    
    
        /***
         *   具体策略类   策略接口子类   新客户价格
         */
         static class NewCustomerStrategy implements PriceStrategy {
            @Override
            public BigDecimal getPrice(BigDecimal price) {
                System.out.println("抱歉!新客户没有折扣!");
                return price;
            }
        }
    
        /***
         *   具体策略类   策略接口子类  老客户价格
         */
        static class OldCustomerStrategy implements PriceStrategy {
            @Override
            public BigDecimal getPrice(BigDecimal price) {
                System.out.println("恭喜!老客户打9折");
                price = price.multiply(new BigDecimal(0.9))
                             .setScale(2, BigDecimal.ROUND_HALF_UP);
                return price;
            }
        }
    
    
        /***
         *   具体策略类   策略接口子类   VIP客户价格
         */
        static class VIPCustomerStrategy implements PriceStrategy {
            @Override
            public BigDecimal getPrice(BigDecimal price) {
                System.out.println("恭喜!VIP客户享有8折优惠!");
                price = price.multiply(new BigDecimal(0.8))
                             .setScale(2, BigDecimal.ROUND_HALF_UP);
                return price;
            }
        }
    
    
        /***
         *   具体策略类   策略接口子类   新增MVP
         */
        static class MVPCustomerStrategy implements PriceStrategy {
            @Override
            public BigDecimal getPrice(BigDecimal price) {
                System.out.println("哇偶!MVP客户享受7折优惠!!!");
                price = price.multiply(new BigDecimal(0.7))
                             .setScale(2,BigDecimal.ROUND_HALF_UP);
                return price;
            }
        }
    }
    View Code

    调用老用户策略 MVP策略

    结果如下

    3.怎么使用策略模式

    两个数加减法

    例子4

    public class Calculator {
    
        //加符号
        private final static String ADD = "+";
        //减符号
        private final static String SUB = "-";
    
        //加法运算
        private int add(int a, int b) {
            return a + b;
        }
    
        //减法运算
        private int sub(int a, int b) {
            return a - b;
        }
    
        public int exec(int a, int b, String operator) {
            int result = 0;
            if (operator.equals(ADD)) {
                result = this.add(a, b);
            } else if (operator.equals(SUB)) {
                result = this.sub(a, b);
            }
            return result;
        }
    }
    View Code

    例子4 简化写法

    public class Calculator2 {
        //加符号
        private final static String ADD = "+";
        // 减符号
        private final static String SUB = "-";
    
        public int exec(int a, int b, String operator) {
            return operator.equals(ADD) ? a + b : a - b;
        }
    }
    View Code

    测试

     结果如下

     例子4 使用策略模式

    public class StrategyPattern4 {
    
        public static void main(String[] args) {
    
            Calculator add = new Add();
            int result = add.exec(3, 6);
            System.out.println("result = " + result);
    
            Calculator sub = new Sub();
            int result2 = sub.exec(3, 6);
            System.out.println("result2 = " + result2);
    
        }
    
        interface Calculator {
            public int exec(int a, int b);
        }
    
    
        class Context {
    
            private Calculator cal;
    
            public Context(Calculator cal) {
                this.cal = cal;
            }
    
            public int exec(int a, int b, String symbol) {
                return this.cal.exec(a, b);
            }
        }
    
    
        public static class Add implements Calculator {
            //加法运算
            @Override
            public int exec(int a, int b) {
                return a + b;
            }
        }
    
        public static class Sub implements Calculator {
            //减法运算
            @Override
            public int exec(int a, int b) {
                return a - b;
            }
        }
    }
    View Code

    测试

    结果如下

    例子4 使用策略枚举    写法更简练 调用清楚

    /***
     *功能描述  策略枚举
     */
    public enum Calculator3 {
        //加法运算
        ADD("+") {
            @Override
            public int exec(int a, int b) {
                return a + b;
            }
        },
    
        //减法运算
        SUB("-") {
            @Override
            public int exec(int a, int b) {
                return a - b;
            }
        };
    
        String value = "";
    
        //定义成员值类型
        private Calculator3(String value) {
            this.value = value;
        }
    
        //获得枚举成员的值
        public String getValue() {
            return this.value;
        }
    
        //声明一个抽象方法
        public abstract int exec(int a, int b);
    
    }
    View Code

    测试

     结果如下

    测试类

    public class client {
        public static void main(String[] args) {
    
            System.out.println("运行结果为:=" + new Calculator().exec(3,6,"+"));
            System.out.println("运行结果为:=" + new Calculator().exec(3,6,"-"));
    
            System.out.println("运行结果为:=" + new Calculator2().exec(3,6,"+"));
            System.out.println("运行结果为:=" + new Calculator2().exec(3,6,"-"));
    
            System.out.println("运行结果为:=" + Calculator3.ADD.exec(3, 6));
            System.out.println("运行结果为:=" + Calculator3.SUB.exec(3, 6));
        }
    }
    古人学问无遗力,少壮工夫老始成。 纸上得来终觉浅,绝知此事要躬行。
  • 相关阅读:
    欧拉服务器安装虚拟机(根据open欧拉教程编写vnc)
    Pytest生成html测试报告
    FastAPI8路径参数和数值校验
    pytest不在终端执行的方式
    Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content
    JAVA日报
    JAVA日报
    JAVA日报
    JAVA日报
    JAVA日报
  • 原文地址:https://www.cnblogs.com/wf-zhang/p/14888752.html
Copyright © 2020-2023  润新知