设计模式-装饰器模式

写在前面

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
相关推荐
又是努力搬砖的一年4 分钟前
SpringBoot中,接口加解密
java·spring boot·后端
0wioiw013 分钟前
Python基础(Flask①)
后端·python·flask
风象南41 分钟前
SpringBoot 自研运行时 SQL 调用树,3 分钟定位慢 SQL!
spring boot·后端
Jenny1 小时前
第九篇:卷积神经网络(CNN)与图像处理
后端·面试
大志说编程1 小时前
LangChain框架入门16:智能客服系统RAG应用实战
后端·langchain·aigc
沸腾_罗强1 小时前
Redis内存爆了
后端
天天摸鱼的java工程师1 小时前
Snowflake 雪花算法优缺点(Java老司机实战总结)
java·后端·面试
海梨花2 小时前
【从零开始学习Redis】项目实战-黑马点评D2
java·数据库·redis·后端·缓存
bug菌2 小时前
零基础也能做出AI应用?Trae是如何打破编程"高墙"的?
后端·ai编程·trae