设计模式-装饰器模式

写在前面

Hello,我是易元,这篇文章是我学习设计模式时的笔记和心得体会。如果其中有错误,欢迎大家留言指正!

代码初期的快速实现

场景:互联网初创公司"极客海淘",团队只有3个成员(小易、产品小美、测试大哥老李),迎来了系统的第一次需求扩张(折扣),老板大手一挥:"先用起来再说!"

kotlin 复制代码
/** 
 * 订单逻辑处理器 
 */ 
public class OrderProcessor { 
    public double process(Double amount) { 
        System.out.println("计算订单金额:" + amount); 
        return amount; 
    } 
} 

/** 
 * 订单折扣处理器 
 */ 
public class DiscountOrderProcessor extends OrderProcessor { 
    private Double discount; 

    public DiscountOrderProcessor(Double discount) { 
        this.discount = discount; 
    } 

    public double process(Double amount) { 
        double process = super.process(amount); 
        System.out.println("订单折扣:" + discount); 
        System.out.println("商品折扣金额:" + (process * discount)); 
        return amount - process * discount; 
    } 
} 

团队日常
小易(叉腰):"搞定!"

紧急功能的应对方案

团队日常
产品小美(眨眼):"易哥,还能加个进口关税功能吗?客户提出的需求,而且催得紧~"
老李(摸鱼):"别慌,反正现在代码简单~"

订单关税处理器
kotlin 复制代码
public class TariffOrderProcessor extends OrderProcessor { 
    private Double tariff; 

    public TariffOrderProcessor(Double tariff) { 
        this.tariff = tariff; 
    } 

    public double process(Double amount) { 
        System.out.println("商品关税:" + tariff); 
        System.out.println("商品关税金额:" + amount * tariff); 
        return super.process(amount * tariff + amount); 
    } 
} 
订单关税 折扣 处理器
kotlin 复制代码
public class TariffDiscountOrderProcessor extends DiscountOrderProcessor { 
    private Double tariff; 

    public TariffDiscountOrderProcessor(Double tariff, Double discount) { 
        super(discount); 
        this.tariff = tariff; 
    } 

    public double process(Double amount) { 
        System.out.println("商品关税比例:" + tariff); 
        System.out.println("商品关税金额:" + (amount * tariff)); 
        return super.process(amount + amount * tariff); 
    } 
} 

设计缺陷显形

团队日常
产品小美(递咖啡):"易哥辛苦了,能再加赠品功能吗?客户说下次一定..."
小易(抓头发):"这继承树是要捅破天花板啊!"
老李(拍桌子):"测试用例要写疯了!这代码没法维护!"

累加功能存在的隐患

问题清单

  1. 类爆炸 :每加一个功能就继承一个子类,现在代码库里有TariffDiscountOrderProcessorOrderProcessorDiscountOrderProcessor...
  2. 功能耦合:进口订单和赠品功能写死在一起,无法单独存在
  3. 维护地狱:改个税率要改10个类!

引入设计模式重构

场景 :小易为了不被人说是屎山,偷偷学习了《设计模式之美》,决心用装饰器模式拯救订单系统。
设计模式选择 :装饰器模式(Decorator Pattern)
核心目标:优雅扩展,让产品经理的嘴不再开过山车

装饰器模式四要素
角色 职责 订单系统示例
Component 定义基础操作的接口 OrderDecorator
ConcreteComponent 基础实现类 OrderProcessorImpl
Decorator 持有组件引用并实现相同接口 OrderDecorator
ConcreteDecorator 添加具体功能的装饰器 DiscountDecorator

重构:装饰器模式实践

步骤1:定义组件接口(订单处理基类)
java 复制代码
public abstract class OrderDecorator implements OrderProcessor { 
    protected final OrderProcessor processor; 

    protected OrderDecorator(OrderProcessor processor) { 
        this.processor = processor; 
    } 

    @Override 
    public abstract double process(Double amount); 
} 
步骤2:实现基础组件(裸奔版处理器)
kotlin 复制代码
public class OrderProcessorImpl implements OrderProcessor { 
    @Override 
    public double process(Double amount) { 
        System.out.println("------------------订单基础处理------------------"); 
        System.out.println("计算订单金额:" + amount); 
        System.out.println("订单基础逻辑处理......."); 
        System.out.println("------------------------------------------------"); 
        return amount; 
    } 
} 
步骤3:创建装饰器基类(功能扩展骨架)
java 复制代码
public abstract class OrderDecorator implements OrderProcessor {

    protected final OrderProcessor processor;

    protected OrderDecorator(OrderProcessor processor) {
        this.processor = processor;
    }

    @Override
    public abstract double process(Double amount);
}
步骤4:实现具体装饰器(功能插件)
kotlin 复制代码
// 订单打折处理器类(具体装饰器)  
public class DiscountDecorator extends OrderDecorator { 
    private final Double discount; 

    protected DiscountDecorator(OrderProcessor processor, Double discount) { 
        super(processor); 
        this.discount = discount; 
    } 

    @Override 
    public double process(Double amount) { 
        System.out.println("------------------订单打折处理------------------"); 
        System.out.println("商品订单金额:" + amount); 
        System.out.println("订单折扣:" + discount); 
        System.out.println("商品折扣金额:" + (amount * discount)); 
        System.out.println("------------------------------------------------"); 
        return super.processor.process(amount * (1 - discount)); 
    } 
} 

// 订单关税处理器类(具体装饰器)  
public class TariffDiscountDecorator extends OrderDecorator { 
    private final Double tariff; 

    protected TariffDiscountDecorator(OrderProcessor processor, Double tariff) { 
        super(processor); 
        this.tariff = tariff; 
    } 

    @Override 
    public double process(Double amount) { 
        System.out.println("------------------订单关税处理------------------"); 
        System.out.println("商品订单金额:" + amount); 
        System.out.println("商品关税比例:" + tariff); 
        System.out.println("商品关税金额:" + (amount * tariff)); 
        System.out.println("------------------------------------------------"); 
        return super.processor.process(amount * (1 + tariff)); 
    } 
} 
测试代码
arduino 复制代码
public class OrderProcessorTest { 
    @Test 
    public void discountTest() { 
        OrderProcessor orderDecorator = new OrderProcessorImpl(); 

        // 促销增加 10% 折扣  
        orderDecorator = new DiscountDecorator(orderDecorator, 0.1); 

        // 增加关税  
        orderDecorator = new TariffDiscountDecorator(orderDecorator, 0.3); 

        double process = orderDecorator.process(400D); 
        System.out.println("订单实际金额:" + process); 
    } 
} 

重构后效果

系统改进点
  • 动态组合:运行时任意组合功能
  • 正交扩展:新增装饰器不影响现有逻辑
  • 类型安全:所有装饰器实现统一接口
  • 顺序敏感:装饰顺序影响最终结果(符合业务特性)
复杂度对比
指标 重构前 重构后
类数量 O(2ⁿ) O(n)
新增功能成本 修改现有类 新增装饰器类
测试覆盖率 60% 95%

赠品需求实现

kotlin 复制代码
public class GiftDecorator extends OrderDecorator { 
    private final String giftName; 

    protected GiftDecorator(OrderProcessor processor, String giftName) { 
        super(processor); 
        this.giftName = giftName; 
    } 

    @Override 
    public double process(Double amount) { 
        System.out.println("------------------订单赠品处理------------------"); 
        System.out.println("商品订单金额:" + amount); 
        System.out.println("商品赠品名称:" + giftName); 
        System.out.println("-----------------------------------------------"); 
        return super.processor.process(amount); 
    } 
} 

测试代码

ini 复制代码
public class OrderProcessorTest { 
    @Test 
    public void discountTest() { 
        OrderProcessor orderDecorator = new OrderProcessorImpl(); 

        orderDecorator = new GiftDecorator(orderDecorator, "灰太狼玩偶"); 
        orderDecorator = new DiscountDecorator(orderDecorator, 0.1); 
        orderDecorator = new TariffDiscountDecorator(orderDecorator, 0.3); 

        double process = orderDecorator.process(400D); 
        System.out.println("订单实际金额:" + process); 
    } 
} 

团队新日常

小易(转着笔):"加个新功能?写个装饰器五分钟搞定~" 老李(喝着茶):"测试用例都不用改,舒坦!"
小美(星星眼):"易哥,今晚我请喝奶茶!"

长话短说

核心思想:通过组合实现功能的动态叠加,保持类职责单一性(想加功能就加层装饰,拆开来看每个装饰器只管一件事)

何时选择装饰器模式?

  • 需要动态、透明地扩展对象功能
  • 不宜使用子类扩展(避免类爆炸)
  • 需要运行时组合不同功能

何时避免使用?

  • 扩展功能需要完全改变接口
  • 装饰顺序不影响结果时(可能过度设计)
  • 性能敏感的底层操作(装饰器可能引入开销)

适用场景特征

  1. 需要动态、透明地添加职责
  2. 不能使用继承或需要避免子类膨胀
  3. 需要撤销或替换已添加的功能

代码编写步骤

  1. 定义组件接口(OrderComponent)
  2. 创建基础实现类(BasicOrder)
  3. 创建装饰器基类(OrderDecorator)
  4. 实现具体装饰器(ImportTaxDecorator)
  5. 客户端按需组合装饰器

示例代码结构

kotlin 复制代码
public interface Component { ... }          // 组件接口 
public class ConcreteComponent implements Component { ... }  // 基础实现类  
public abstract class Decorator implements Component { ... } // 装饰器基类  
public class ConcreteDecoratorA extends Decorator { ... }    // 具体装饰器 A
public class ConcreteDecoratorB extends Decorator { ... }    // 具体装饰器 B
相关推荐
止语Lab27 分钟前
好的 DX 不等于少写代码——三种语言的摩擦力设计课
后端
吃饱了得干活27 分钟前
别再手动解析 LLM 输出了!LangChain 四种结构化输出方案对比
后端·python·langchain
程序员天天困32 分钟前
Arthas trace 命令怎么用?一行定位最慢那行代码
jvm·后端
Huiturn32 分钟前
GPT 5.6 连续编码 10 小时,纯 Python 啃下 Word 二进制格式——doc2docx 实现拆解
后端
用户2986985301439 分钟前
Python 实现 Excel 与 Markdown 互转的实用指南
后端·python·excel
用户772831049084041 分钟前
krono-job:零侵入、单二进制交付的分布式任务调度平台(开源)
后端
Conan在掘金1 小时前
鸿蒙报错速查:Function lacks ending return statement,返回路径漏 return 就炸,根因 + 真解法
后端
人间凡尔赛1 小时前
AI-Native 云原生架构:2026 年从容器编排到智能体编排的范式革命
后端·云原生·架构
IT_陈寒2 小时前
Vue的响应式让我加班到凌晨3点,原来问题出在这
前端·人工智能·后端
卷无止境2 小时前
提升 Python 代码健壮性的方法大盘点
后端·python