单一大类混杂职责会导致修改困难、测试失效、协作冲突;应通过策略模式拆分可变逻辑、事件总线解耦上下游、组合替代继承注入依赖,并依复用性划清服务边界。

一个类塞满所有业务逻辑会出什么问题
这种设计在初期看似省事,但很快会暴露:修改某个小功能得翻几百行、加个新接口要改 BusinessManager::handleOrder() 和 BusinessManager::notifyUser() 两处、单元测试根本没法写——因为 BusinessManager 依赖数据库、网络、定时器、日志系统,全耦合在一起。更麻烦的是,多人协作时经常出现“我改了支付流程,结果退款单生成失败”这类隐性冲突。
核心症结不是代码多,而是职责混杂:它既是调度员、又是执行者、还是数据搬运工和错误翻译官。
用策略模式拆分可变的业务规则
当不同客户/渠道/地区需要走不同校验或计费逻辑时,别在 if-else 里硬编码分支,而是把每种规则封装成独立类:
- 定义统一接口:
class PricingStrategy { public: virtual double calculate(const Order& o) = 0; };
- 为每个场景实现子类:
StandardPricing、VIPDiscountPricing、OverseasTaxPricing
- 运行时注入具体策略:
orderProcessor.setPricingStrategy(std::make_unique<vipdiscountpricing>());</vipdiscountpricing>
这样新增一种计费方式,只需加一个类,不碰原有逻辑;测试也只需 mock 接口,不用启数据库。
用事件总线解耦上下游操作
下单成功后要发短信、更新库存、触发风控扫描——这些操作本就不该由订单服务同步执行。改成发布 OrderPlacedEvent,让独立的 SmsService、InventoryUpdater、RiskScanner 各自订阅处理。
- 避免阻塞主流程:发短信超时不会导致订单创建失败
- 便于横向扩展:短信服务挂了,库存更新照常进行
- 调试友好:用日志或工具查
OrderPlacedEvent 是否发出、被谁消费、耗时多少
注意别把事件对象设计成大而全的 OrderFullData,只传必要字段(如 order_id、user_id),下游按需查库——否则一次事件变更牵扯所有订阅者。
用组合代替继承来组装能力
别让 BusinessManager 继承 DatabaseHelper、HttpClient、Logger——这等于把工具链写死进业务核心。改为成员变量持有接口指针:
class BusinessManager {
std::unique_ptr<DatabaseInterface> db_;
std::unique_ptr<HttpInterface> http_;
std::shared_ptr<Logger> logger_;
public:
BusinessManager(std::unique_ptr<DatabaseInterface> db,
std::unique_ptr<HttpInterface> http,
std::shared_ptr<Logger> log)
: db_(std::move(db)), http_(std::move(http)), logger_(log) {}
};
构造时注入,测试时换 mock 实现;上线后可按环境切换 MySQL/PostgreSQL 实现,不影响业务逻辑本身。
复杂点往往不在怎么拆,而在边界划在哪——比如“用户积分变动”该算在订单服务里,还是单独的积分服务?判断依据只有一个:这个变动是否会被其他业务(如签到、抽奖)同样触发。如果是,它就该独立。
class PricingStrategy { public: virtual double calculate(const Order& o) = 0; };
StandardPricing、VIPDiscountPricing、OverseasTaxPricing
orderProcessor.setPricingStrategy(std::make_unique<vipdiscountpricing>());</vipdiscountpricing>
OrderPlacedEvent,让独立的 SmsService、InventoryUpdater、RiskScanner 各自订阅处理。
- 避免阻塞主流程:发短信超时不会导致订单创建失败
- 便于横向扩展:短信服务挂了,库存更新照常进行
- 调试友好:用日志或工具查
OrderPlacedEvent是否发出、被谁消费、耗时多少
OrderFullData,只传必要字段(如 order_id、user_id),下游按需查库——否则一次事件变更牵扯所有订阅者。


















