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和分层架构中常见模式的分布。你可以把它当作一个参考地图。

MVC + 分层架构模式全景图 表现层 (View + Controller) MVC / MVP / MVVM · 观察者模式 · 命令模式 · 组合模式 业务层 (Model / Service) 策略模式 · 状态模式 · 模板方法 · 责任链模式 数据访问层 (DAO / Repository) 仓储模式 · 工厂模式 · 代理模式 · 适配器模式 箭头表示依赖方向:表现层依赖业务层,业务层依赖数据访问层

这张图里,每一层都列出了最常用的模式。你不需要全部记住,但遇到具体问题时,可以回来翻一翻。我自己的经验是:80%的场景,用上图中2-3个模式组合就够了

总结一下

MVC和分层架构是骨架,设计模式是血肉。没有模式的架构是僵硬的,没有架构的模式是散乱的。两者结合,才能构建出优雅、可维护的软件系统。

最后送大家一句话:模式是经验的结晶,不是教条的枷锁。用的时候多问自己一句:「这个模式真的解决了我的问题吗?」如果答案是肯定的,那就大胆用。


专注资料整理