共计 2440 个字符,预计需要花费 7 分钟才能阅读完成。
背景痛点
在软件开发中,随着业务逻辑的复杂度增加,代码往往会变得高度耦合。这种耦合性带来了一系列问题:

- 难以维护:修改一个功能可能影响多个模块,导致回归测试成本高
- 扩展性差:新增业务需求时,需要在多处修改代码,容易引入错误
- 可读性降低:业务逻辑分散在各处,新成员难以快速理解系统
- 复用困难:相似功能无法直接复用,需要复制粘贴并修改
设计模式对比
skill 设计模式与其他常见解耦模式的对比:
- 与策略模式比较
- 相似点:都支持运行时行为变化
-
差异点:skill 模式更强调业务能力的组合,而策略模式侧重算法的替换
-
与装饰器模式比较
- 相似点:都支持动态添加功能
-
差异点:skill 模式是水平扩展(添加新能力),装饰器是垂直增强(增强现有功能)
-
与命令模式比较
- 相似点:都将操作封装为对象
- 差异点:skill 模式关注业务能力的抽象,命令模式关注操作的封装和执行
核心实现
skill 设计模式的核心思想是将业务能力抽象为独立的 ”skill” 单元,通过组合这些单元来构建复杂业务逻辑。
类图关系
classDiagram
class Context {+executeSkill()
}
class Skill {
<<interface>>
+execute()}
class ConcreteSkillA {+execute()
}
class ConcreteSkillB {+execute()
}
Context o-- Skill
Skill <|.. ConcreteSkillA
Skill <|.. ConcreteSkillB
关键接口设计
- Skill 接口
- 定义统一的执行方法(如 execute)
-
包含必要的上下文参数
-
Context 类
- 维护当前可用的 skill 集合
- 提供 skill 的执行环境
-
处理 skill 间的交互
-
ConcreteSkill 实现
- 每个具体 skill 实现特定业务能力
- 保持单一职责原则
代码示例
以下是一个订单处理的实战案例:
// Skill 接口
public interface OrderProcessingSkill {void process(OrderContext context);
}
// 具体 Skill 实现
public class DiscountCalculationSkill implements OrderProcessingSkill {
@Override
public void process(OrderContext context) {
// 计算折扣逻辑
double discount = calculateDiscount(context);
context.applyDiscount(discount);
}
private double calculateDiscount(OrderContext ctx) {// 具体折扣计算逻辑}
}
public class TaxCalculationSkill implements OrderProcessingSkill {
@Override
public void process(OrderContext context) {
// 税费计算逻辑
double tax = calculateTax(context);
context.applyTax(tax);
}
}
// 上下文
public class OrderProcessor {private List<OrderProcessingSkill> skills = new ArrayList<>();
public void addSkill(OrderProcessingSkill skill) {skills.add(skill);
}
public void processOrder(Order order) {OrderContext context = new OrderContext(order);
for (OrderProcessingSkill skill : skills) {skill.process(context);
}
}
}
// 使用示例
public class Client {public static void main(String[] args) {OrderProcessor processor = new OrderProcessor();
processor.addSkill(new DiscountCalculationSkill());
processor.addSkill(new TaxCalculationSkill());
Order order = new Order(/* 订单数据 */);
processor.processOrder(order);
}
}
性能考量
优势
- 扩展性 :新增业务能力只需添加新 skill,无需修改现有代码
- 灵活性 :可动态组合不同的 skill 应对不同场景
- 可测试性 :每个 skill 可独立测试
劣势
- 性能开销 :方法调用的间接性会带来轻微性能损耗
- 内存占用 :每个 skill 都是独立对象,可能增加内存使用
- 调试复杂度 :业务逻辑分散在多个 skill 中,调试时可能需要追踪多个对象
避坑指南
- skill 粒度过细
- 问题:创建过多微小 skill 导致系统复杂
-
解决:合理划分 skill 的职责范围,保持适度粒度
-
上下文膨胀
- 问题:context 类包含过多状态和方法
-
解决:按功能模块拆分 context,或使用分层设计
-
skill 间依赖
- 问题:skill 之间存在隐性依赖
-
解决:明确声明依赖关系,或通过 context 中介
-
执行顺序问题
- 问题:某些 skill 需要特定执行顺序
- 解决:引入优先级机制或显式配置执行顺序
总结与思考
skill 设计模式为解决复杂业务逻辑的耦合问题提供了一种优雅的方案。它通过将业务能力抽象为独立的 skill 单元,实现了关注点分离和灵活组合。在实际项目中应用时,需要考虑业务场景的具体需求,合理设计 skill 的粒度和交互方式。
你可以思考以下问题来评估是否适合在你的项目中使用 skill 模式:
- 你的业务逻辑是否经常变化或需要灵活组合?
- 系统是否面临多个业务能力的扩展需求?
- 当前代码是否存在高度耦合导致的维护困难?
如果答案是肯定的,那么 skill 设计模式可能正是你需要的解决方案。
正文完
