设计模式-装饰器模式

写在前面

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
相关推荐
声声codeGrandMaster2 小时前
Django项目入门
后端·mysql·django
千里码aicood2 小时前
【2025】基于springboot+vue的医院在线问诊系统设计与实现(源码、万字文档、图文修改、调试答疑)
vue.js·spring boot·后端
yang_love10113 小时前
Spring Boot 中的 @ConditionalOnBean 注解详解
java·spring boot·后端
Pandaconda4 小时前
【后端开发面试题】每日 3 题(二十)
开发语言·分布式·后端·面试·消息队列·熔断·服务限流
鱼樱前端4 小时前
mysql事务、行锁、jdbc事务、数据库连接池
java·后端
Adellle5 小时前
MySQL
数据库·后端·mysql
JavaGuide5 小时前
Kafka 4.0 正式发布,彻底抛弃 Zookeeper,队列功能来袭!
后端·kafka
轻松Ai享生活6 小时前
2030年的大模型将会是什么样的?机械可解释性又是什么?
人工智能·后端·面试
uhakadotcom6 小时前
解锁网页解析的秘密:BeautifulSoup4 入门指南
后端·面试·github
冯渺岚7 小时前
Lua语言的配置管理
开发语言·后端·golang