• 设计模式之策略模式


    引言

    从自我理解的角度上看,策略模式,策略即为
    办法/解决方法,对于某个问题,一般能够衍生出多种解决方法。当然,策略模式中的策略应该也是这个由来,在解决问题时,能够有多种方案/办法
    或者说策略。

    应用场景:
    1. 比如我出行,我可以坐飞机、坐高铁、坐火车、轮船 或者是自己开车
    2. 比如说在销售的时候商家是满300-30 还是或者是打折 ,采用哪种策略能够使得方案最佳。
    由此,引出策略模式的定义:
    在大话设计模式中的定义是这样的。
    策略模式: 它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。
    贴下书上策略模式结构图

    优点:

    策略类之间可以自由切换
    由于策略类都实现同一个接口,所以使它们之间可以自由切换。

    易于扩展
    增加一个新的策略只需要添加一个具体的策略类即可,基本不需要改变原有的代码,符合“开闭原则“

    避免使用多重条件选择语句(if else),充分体现面向对象设计思想。

    缺点:

    客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
    策略模式将造成产生很多策略类,可以通过使用享元模式在一定程度上减少对象的数量。

    策略模式三大要素
    环境(Context):有一个Strategy类的引用,和具体的策略类交互。
    抽象策略(Strategy)角色:一个接口或抽象类,给出规范。
    具体策略(ConcreteStrategy)角色:具体算法或行为。

    某电影院售票系统为不同类型的用户提供了不同的打折方式(Discount),学生凭学生证可享受8折优惠(StudentDiscount),儿童可享受减免10元的优惠(ChildrenDiscount),VIP用户除享受半价优惠外还可以进行积分(VIPDiscount)。策略模式类图如下:
    在这里插入图片描述

    抽象类Discount定义策略的折扣方法,并抽象出来一个公共属性。

    package strategy;
    
    /**
     * @Author Tang
     * 抽象策略(Discount)角色:一个接口或抽象类,给出规范。
     **/
    
    public abstract class Discount {
    
     // 每种策略的优惠政策
     public double discountPrice;
     public abstract double calculate(double price);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    儿童门票

    package strategy;
    
    /**
     * @Author Tang
     **/
    public class ChildrenDiscount extends Discount{
    
        public   ChildrenDiscount(double price){
            this.discountPrice =price;
        }
        @Override
        public double calculate(double price) {
            return price - discountPrice;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    学生门票

    package strategy;
    
    /**
     * @Author Tang
     * 具体策略 学生策略
     **/
    public class StudentDiscount extends Discount{
    
    
        public StudentDiscount(double discountPrice) {
            this.discountPrice = discountPrice;
        }
        @Override
        public double calculate(double price) {
            return price * discountPrice;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    VIP门票

    package strategy;
    
    /**
     * @Author Tang
     * VIP策略
     **/
    public class VIPDiscount extends Discount{
        public VIPDiscount(double price){
            this.discountPrice = price;
        }
        @Override
        public double calculate(double price) {
            return price * discountPrice;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    定义Context为MovieTicket ,这里需要有一个Discount的引用

    package strategy;
    
    /**
     * @Author Tang
     *  环境 Context 有一个Strategy的引用
     **/
    public class MovieTicket {
    
        // Strategy的引用
        private Discount discount = null;
    
        private double price;
    
        public MovieTicket(Discount discount){
          this.discount = discount;
      }
    
      // 计算逻辑 计算出优惠后的价钱
        public void setPrice(double price){
            // 调用每个具体策略的方法来分别计算出价格
           this.price = discount.calculate(price);
        }
        public double getPrice(){
            return this.price;
        }
        public void setDiscount(Discount discount){
            this.discount =discount;
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    package strategy;
    
    import java.util.Scanner;
    
    /**
     * @Author Tang
     **/
    public class StrategyTest {
    
        private static  double totalPrice;
    
        public static void main(String[] args) {
            while(true){
                Scanner scanner = new Scanner(System.in);
                System.out.println("请输入打折方案:");
                String str = scanner.next();
                MovieTicket ticket = null;
                switch (str){
                    case "学生优惠":
                        ticket = new MovieTicket(new StudentDiscount(0.8));
                        break;
                    case "儿童优惠":
                        ticket = new MovieTicket(new ChildrenDiscount(10));
                        break;
                    case "会员优惠":
                        ticket = new MovieTicket(new VIPDiscount(0.5));
                        break;
                }
                System.out.println("请输入门票原价:");
                double oriPrice =scanner.nextInt();
                ticket.setPrice(oriPrice);
                System.out.println("优惠后的票价为:"+ ticket.getPrice());
            }
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
  • 相关阅读:
    安卓基础学习 Day19|安卓高级控件------下拉列表
    ASP.NET Core - 选项系统之选项配置
    MySQL之导入导出&视图&索引&执行计划
    010.Springboot之养老院管理系统
    CentOS7.9离线安装Docker环境
    React 路由总结 react-router-dom6+react-router-dom5
    LuatOS-SOC接口文档(air780E)-- gtfont - 高通字库芯片
    『现学现忘』Docker基础 — 16、Docker中的基本概念和底层原理
    待看12313132
    android8.1- Show virtual keyboard 默认打开
  • 原文地址:https://blog.csdn.net/qq_50629351/article/details/126714104