35. 设计模式与架构设计:MVC架构中的模式应用,分层架构中的模式组合
聊到架构设计,很多同学第一反应就是「分层」。没错,分层是软件工程里最朴素的智慧。但光分层还不够,你得知道每一层里该用什么模式来组织代码。今天我就结合MVC和分层架构,聊聊我这些年积累的一些经验。
MVC架构里的模式影子
MVC本身不是设计模式,它是一种架构模式。但MVC的每一层,都大量使用了经典的设计模式。我习惯把MVC拆开来看:
- Model层:观察者模式、策略模式
- View层:组合模式、模板方法模式
- Controller层:命令模式、策略模式
举个例子,Model层的数据变化要通知View更新。这其实就是观察者模式。我在项目中遇到过一种情况:多个View订阅同一个Model,Model一改,所有View都得刷新。用观察者模式实现,代码干净又解耦。
核心思路:MVC的每一层都可以用设计模式来「加固」。模式不是硬塞进去的,而是自然浮现的。
分层架构中的模式组合
分层架构(比如三层架构)和MVC很像,但更强调职责分离。我见过很多团队把业务逻辑全塞在Controller里,结果Controller膨胀到几千行。说白了,就是没用好模式。
我个人习惯在分层架构里这样组合模式:
| 层次 | 常用模式 | 作用 |
|---|---|---|
| 表现层 | MVC、MVP、MVVM | 分离UI和业务逻辑 |
| 业务层 | 策略模式、模板方法、状态模式 | 封装变化、复用流程 |
| 数据访问层 | 仓储模式、工厂模式、代理模式 | 屏蔽数据源差异 |
你想想看,如果业务层里有一堆if-else判断不同的计算规则,那策略模式就是你的救星。我曾经接手过一个项目,里面全是switch-case,改一个规则要动好几个文件。后来我用策略模式重构,每个规则一个类,新增规则只需要加一个类,完全符合开闭原则。
一个实际案例:订单处理系统
假设我们要做一个订单处理系统。订单状态有:待支付、已支付、已发货、已完成。每个状态下的操作不同。你会怎么设计?
我建议用状态模式 + 策略模式组合。状态模式管理订单的生命周期,策略模式处理不同支付方式。
// 状态模式:订单状态
class OrderState {
public:
virtual void pay(Order* order) = 0;
virtual void ship(Order* order) = 0;
virtual void complete(Order* order) = 0;
virtual ~OrderState() = default;
};
class PendingState : public OrderState {
public:
void pay(Order* order) override {
// 执行支付逻辑
order->setState(new PaidState());
}
void ship(Order* order) override {
// 待支付不能发货
throw std::runtime_error("Cannot ship unpaid order");
}
void complete(Order* order) override {
throw std::runtime_error("Cannot complete unpaid order");
}
};
// 策略模式:支付方式
class PaymentStrategy {
public:
virtual void pay(double amount) = 0;
virtual ~PaymentStrategy() = default;
};
class CreditCardPayment : public PaymentStrategy {
public:
void pay(double amount) override {
// 信用卡支付逻辑
}
};
class WeChatPayment : public PaymentStrategy {
public:
void pay(double amount) override {
// 微信支付逻辑
}
};
这样设计的好处是:状态变化和支付方式变化互不干扰。你新增一个「退款中」状态,只需要加一个类;新增一个「支付宝支付」,也只需要加一个类。嗯,这就是模式组合的魅力。
小技巧:模式组合时,注意不要让模式之间产生循环依赖。比如状态模式里不要直接依赖策略模式的具体实现,通过接口交互就好。
避坑指南:我曾经踩过的坑
我曾经在一个项目里过度使用模式。一个简单的CRUD接口,我硬是套上了工厂模式、代理模式、装饰器模式。结果代码变得极其复杂,新同事看了三天没看懂。后来我反思:模式是工具,不是目的。分层架构里,模式组合要遵循一个原则——只在变化点使用模式。
举个例子,如果你的业务逻辑几乎不变,那模板方法模式就是多余的。如果你的数据源只有一种,那仓储模式就是过度设计。说白了,模式是为变化服务的。
注意:不要为了用模式而用模式。架构设计的第一原则是「简单」。模式组合的前提是:你确实遇到了多个维度的变化。
MVC + 分层架构的模式全景图
下面这张图是我自己总结的,展示了MVC和分层架构中常见模式的分布。你可以把它当作一个参考地图。
这张图里,每一层都列出了最常用的模式。你不需要全部记住,但遇到具体问题时,可以回来翻一翻。我自己的经验是:80%的场景,用上图中2-3个模式组合就够了。
总结一下
MVC和分层架构是骨架,设计模式是血肉。没有模式的架构是僵硬的,没有架构的模式是散乱的。两者结合,才能构建出优雅、可维护的软件系统。
最后送大家一句话:模式是经验的结晶,不是教条的枷锁。用的时候多问自己一句:「这个模式真的解决了我的问题吗?」如果答案是肯定的,那就大胆用。