Java设计模式—策略模式(商场打折)

策略这个词应该怎么理解,打个比方说,我们出门的时候会选择不同的出行方式,比如骑自行车、坐公交、坐火车、坐飞机、坐火箭等等,这些出行方式,每一种都是一个策略。

  再比如我们去逛商场,商场现在正在搞活动,有打折的、有满减的、有返利的等等,其实不管商场如何进行促销,说到底都是一些算法,这些算法本身只是一种策略,并且这些算法是随时都可能互相替换的,比如针对同一件商品,今天打八折、明天满100减30,这些策略间是可以互换的。

策略模式是一种行为型设计模式,它允许在运行时选择算法的行为。在这个设计模式中,可以定义一系列的算法,将每种算法封装到单独的类中,并使它们可以相互替换。这样可以使算法的变化独立于使用算法的客户端。

在这个打折策略的例子中,我们使用了策略模式来实现不同的打折算法,包括正常收费、打折收费和返利收费。下面是策略模式的主要组成部分及其作用:

  1. 策略接口(CashSuper):定义了一个算法族的公共接口,其中包含了所有具体算法类所需的方法。在这个例子中,CashSuper接口定义了acceptCash方法,用于计算最终的收费金额。

  2. 具体策略类:每个具体策略类实现了策略接口,提供了特定的算法实现。在这个例子中,CashNormal、CashDiscount和CashReturn分别是具体策略类,分别表示了正常收费、打折收费和返利收费的算法实现。

  3. 上下文类(CashContext):上下文类持有一个策略对象的引用,并在运行时根据客户端的需要选择合适的策略。在这个例子中,CashContext类根据传入的打折类型选择对应的打折策略,并在客户端请求时调用选定策略的方法。

通过使用策略模式,我们可以方便地扩展和修改打折算法,而不必更改客户端的代码。例如,如果需要新增打折方式或修改现有的打折方式,只需创建新的具体策略类或修改现有的策略类,而不会影响到CashContext类或客户端的代码。这样的设计使得系统更加灵活和可维护。

另外,策略模式还有利于代码的复用,因为每个具体策略类都是独立的,可以在不同的上下文中重复使用。同时,由于算法的实现被封装到了具体策略类中,客户端可以专注于业务逻辑,而无需关注具体的算法实现细节。

总之,策略模式通过将算法封装成独立的策略类,并在运行时动态选择合适的策略,实现了算法的可插拔、可扩展和可维护的特性,是一种非常实用的设计模式。

java 复制代码
package com.ss.qrcode.test;

public class CashContext {
    private CashSuper cs;

    /**
     *  定义打折类型枚举
     */
    public enum TYPE {
        /**
         * 正常收费
         */
        NORMAL,
        /**
         *  打折收费
         */
        CASH_DISCOUNT,
        /**
         *  返利收费
         */
        CASH_RETURN
    }

    public CashContext(TYPE t) {
        switch (t) {
            case NORMAL:
                cs = new CashNormal();
                break;
            // 假设打八折
            case CASH_DISCOUNT:
                cs = new CashDiscount(0.8);
                break;
            // 满300返100
            case CASH_RETURN:
                cs = new CashReturn(300, 100);
                break;
            default:
                System.out.println("匹配不符 !");
        }
    }

    /**
     *   定义获取最终价格的方法
     */
    public double getResult(double money) {
        return cs.acceptCash(money);
    }


    public static void main(String[] args) {

        // 输入原价,计算打折后的价格
        // 正常收费
        CashContext context1 = new CashContext(TYPE.NORMAL);
        double result1 = context1.getResult(1000);
        System.out.println("正常收费,结果:" + result1);

        // 打折收费
        CashContext context2 = new CashContext(CashContext.TYPE.CASH_DISCOUNT);
        double result2 = context2.getResult(1000);// 八折
        System.out.println("打折收费,结果:" + result2);

        // 返利收费
        CashContext context3 = new CashContext(TYPE.CASH_RETURN); // 满300返100
        double result3 = context3.getResult(1000);
        System.out.println("返利收费,结果:" + result3);
        }
}
java 复制代码
public class CashDiscount implements CashSuper{

    // 折扣率
    private  double moneyDiscount;

    public CashDiscount(double moneyDiscount){
        this.moneyDiscount = moneyDiscount;
    }
    @Override
    public double acceptCash(double money) {
        return money*moneyDiscount;
    }
}
java 复制代码
public class CashNormal implements  CashSuper{

    @Override
    public double acceptCash(double money) {
        return money;
    }
}
java 复制代码
public class CashReturn implements CashSuper {
    private double moneyCondition; // 满足返利条件的金额
    private double moneyReturn; // 返利金额

    public CashReturn(double moneyCondition, double moneyReturn) {
        this.moneyCondition = moneyCondition;
        this.moneyReturn = moneyReturn;
    }

    @Override
    public double acceptCash(double money) {
        double result = money;
        if (money >= moneyCondition) {
            // 计算返利金额
            result = money - Math.floor(money / moneyCondition) * moneyReturn;
        }
        return result;
    }
}


策略模式的Strategy类层次为Context定义了一系列的可供重用的算法或行为。继承有助于析取出这些算法中的公共功能。对于打折、返利或者其他的算法,其实都是对实际商品收费的一种计算方式,通过继承,可以得到它们的公共功能,公共的功能就是获得计算费用的结果GetResult,这使得算法间有了抽象的父类CashSuper。另外一个策略模式的优点是简化了单元测试,因为每个算法都有自己的类,可以通过自己的接口单独测试。 每个算法可保证它没有错误,修改其中任一个时也不会影响其他的算法。这真的是非常好

相关推荐
爱敲键盘的猴子1 分钟前
深入理解 Java HashMap
java·hashmap
霸道流氓气质2 分钟前
Java开发者AI编程常用MCP、Skills、Rules全景汇总
java·开发语言·ai编程
天涯醉青楼14 分钟前
Spring Boot 接口返回 Bean 时字段名“变形”的深度剖析与解决方案
java
步行cgn31 分钟前
MyBatis 高级映射与延迟加载完全指南
java·tomcat·mybatis
thefool11226632 分钟前
从中序与后序遍历序列构造二叉树
java
吴声子夜歌43 分钟前
Java面试题——JVM(二)
java·开发语言·jvm
CRMEB1 小时前
商城大促活动策划全流程:从定目标到复盘四阶段
java·开发语言·人工智能·ai·开源·php
denglinqings1 小时前
Java开发从入门到精通所有课程
java·开发语言
星空1 小时前
maven镜像
java·maven
chuan.bai2 小时前
Java RAG 实战附录:qwen3 与 bge-m3 模型切换指南
java·人工智能·算法