写在前面
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);
}
}
设计缺陷显形
团队日常 :
产品小美(递咖啡)
:"易哥辛苦了,能再加赠品功能吗?客户说下次一定..."
小易(抓头发)
:"这继承树是要捅破天花板啊!"
老李(拍桌子)
:"测试用例要写疯了!这代码没法维护!"
累加功能存在的隐患
问题清单:
- 类爆炸 :每加一个功能就继承一个子类,现在代码库里有
TariffDiscountOrderProcessor
、OrderProcessor
、DiscountOrderProcessor
... - 功能耦合:进口订单和赠品功能写死在一起,无法单独存在
- 维护地狱:改个税率要改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);
}
}
团队新日常:
小易(转着笔)
:"加个新功能?写个装饰器五分钟搞定~"老李(喝着茶)
:"测试用例都不用改,舒坦!"
小美(星星眼)
:"易哥,今晚我请喝奶茶!"
长话短说
核心思想:通过组合实现功能的动态叠加,保持类职责单一性(想加功能就加层装饰,拆开来看每个装饰器只管一件事)
何时选择装饰器模式?
- 需要动态、透明地扩展对象功能
- 不宜使用子类扩展(避免类爆炸)
- 需要运行时组合不同功能
何时避免使用?
- 扩展功能需要完全改变接口
- 装饰顺序不影响结果时(可能过度设计)
- 性能敏感的底层操作(装饰器可能引入开销)
适用场景特征:
- 需要动态、透明地添加职责
- 不能使用继承或需要避免子类膨胀
- 需要撤销或替换已添加的功能
代码编写步骤:
- 定义组件接口(OrderComponent)
- 创建基础实现类(BasicOrder)
- 创建装饰器基类(OrderDecorator)
- 实现具体装饰器(ImportTaxDecorator)
- 客户端按需组合装饰器
示例代码结构:
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