装饰者模式详解与计费功能实现

装饰者模式详解与计费功能实现

在软件开发中,我们常常需要对某个核心功能不断扩展功能点。如果一味通过继承来实现,就会造成类爆炸------因为每种可能的组合都需要写一个子类。装饰者模式(Decorator Pattern) 就是为了解决这种问题:它允许我们在不修改原有类的情况下,动态地为对象添加新的职责。


一、什么是装饰者模式?

装饰者模式是一种结构型设计模式。它的基本思想是:

  • 定义一个组件接口(Component),声明核心功能。
  • 提供一个具体实现类(ConcreteComponent),实现最核心的功能。
  • 定义抽象装饰类(Decorator),实现Component接口,但内部持有一个Component引用,并把调用委托给这个引用。
  • 不同的装饰实现类(ConcreteDecorator)根据需要增加额外功能,从而"装饰"基础功能。

这种模式具有以下优点:

  1. 避免了继承带来的类膨胀问题。
  2. 运行时可以灵活地组合不同的装饰器,实现不同的功能组合。
  3. 符合开闭原则(对扩展开放,对修改关闭)。

二、案例:计费功能设计

本需求是实现网约车的计费规则:

  1. 起步价:3公里以内,固定收取 13 元。
  2. 里程费:超过 3 公里,每公里收取 2.3 元。
  3. 燃油附加费:单次收取 1 元。

我们使用装饰者模式进行设计。


三、代码实现

1. 定义计价接口

java 复制代码
public interface Valuation {
    float calculation(float km);
}

2. 基础计价功能(只算里程)

java 复制代码
// 基础实现类:负责最基础的里程费用计算
public class BasicValuation implements Valuation {
    private final Valuation next;

    public BasicValuation(Valuation next) {
        this.next = next;
    }

    @Override
    public float calculation(float km) {
        // 基础里程费用
        float price = 0.0f;
        if (km > 3) {
            price += (km - 3) * 2.3f;
        }
        // 传递给下一个装饰器
        if (next != null) {
            price += next.calculation(km);
        }
        return price;
    }
}

3. 起步价装饰器

java 复制代码
// 起步价装饰器
public class StartPriceValuation implements Valuation {
    private final Valuation next;

    public StartPriceValuation(Valuation next) {
        this.next = next;
    }

    @Override
    public float calculation(float km) {
        float price = 13.0f; // 起步价
        if (next != null) {
            price += next.calculation(km);
        }
        return price;
    }
}

4. 燃油附加费装饰器

java 复制代码
// 燃油附加费装饰器
public class FuelCostValuation implements Valuation {
    private final Valuation next;

    public FuelCostValuation(Valuation next) {
        this.next = next;
    }

    @Override
    public float calculation(float km) {
        float price = 1.0f; // 燃油附加费
        if (next != null) {
            price += next.calculation(km);
        }
        return price;
    }
}

5. 组合装饰器

java 复制代码
public class OrderCalculation {

    private static final Valuation valuation = 
        new FuelCostValuation( // 燃油附加费
            new StartPriceValuation( // 起步价
                new BasicValuation(null) // 基础计价
            )
        );

    public static void main(String[] args) {
        float km1 = 2.5f;
        float km2 = 5.0f;

        System.out.println("行程 " + km1 + " km 费用: " + valuation.calculation(km1));
        System.out.println("行程 " + km2 + " km 费用: " + valuation.calculation(km2));
    }
}

四、运行结果

假设:

  • 行程 2.5 km

    • 起步价 13 元 + 燃油 1 元 = 14 元
  • 行程 5 km

    • 起步价 13 元 + (5-3)*2.3=4.6 元 + 燃油 1 元 = 18.6 元

输出结果如下:

复制代码
行程 2.5 km 费用: 14.0
行程 5.0 km 费用: 18.6

五、总结

通过装饰者模式,我们清晰地分离了不同的计费规则(起步价、里程费、燃油附加费),避免了将所有逻辑硬编码在一个类中。新的计费规则只需要新增一个装饰器类即可,大大提高了代码的可扩展性与维护性。

装饰者模式的核心思想是"用组合替代继承,动态地构建功能层次"。尤其在增删功能灵活且变化频繁的业务场景下,装饰者模式格外适用。

相关推荐
子兮曰4 分钟前
Node.js v26.5.0 深度解读:import Text、流式 ReadableStreamTee、以及隐藏的安全加固浪潮
前端·后端·node.js
子兮曰7 分钟前
TypeScript 7.0 RC 深度解读:Go 重写完成,10 倍提速,编译器的「奇点时刻」
前端·后端·typescript
kosan12 分钟前
.NET/C# 实战:我如何把登录验证码从“裸奔”改到“铜墙铁壁”
后端
王中阳Go42 分钟前
AI编程实践:规则 + 技能 + 子代理 + 钩子,拆解Trae AI 开发规范的完整落地范式
后端·agent·ai编程
码事漫谈1 小时前
放下代码洁癖,享受挖坑人生
后端
_张有志_1 小时前
手撕 STL:一棵红黑树,凭什么同时撑起 set 和 map?
后端
妙码生花1 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(二十七):管理员登录验证码开关
前端·后端·ai编程
她的男孩1 小时前
当 Spring Boot 遇上 Flowable 7:Forge 框架企业级工作流引擎架构全解析
人工智能·后端·程序员
java小白小1 小时前
SpringBoot(15):日志框架选型与配置——Logback 从入门到生产级
后端
庄周de蝴蝶2 小时前
两次考试,总算压线通过系统分析师
后端·架构