Skip to content

[L1] Laravel 框架特性与 GoF 设计模式的对应关系

一句话结论

Laravel 的核心组件与 GoF 模式一一对应:服务容器=IoC/DI、Facade=静态代理、事件系统=观察者、Pipeline=责任链、Collection=迭代器。

体系讲解

框架特性 → 设计模式 对照表

Laravel 特性GoF 模式(分类)核心意图映射
服务容器 app()->make()依赖注入 / IoC(创建型)将对象创建与使用解耦,控制权反转给容器
Facades(Cache::get()静态代理(结构型·Proxy)通过 __callStatic 将静态调用转发给容器实例
Route / DB / Cache FacadesGoF 门面(结构型·Facade)为复杂子系统(Router/QueryBuilder)提供简化接口
Eloquent Observer / Event观察者(行为型·Observer)模型事件触发时通知已注册的监听者,发布方不依赖订阅方
HTTP Pipeline(中间件链)责任链变体(行为型·CoR)请求依次经过多个处理节点,每节点调用 $next 传递控制权
Cache / Queue Driver适配器(结构型·Adapter)统一接口对接 Redis/Memcached/File/Database 等不同后端
Collection 链式调用迭代器(行为型·Iterator)封装遍历逻辑,调用方无需感知底层数组结构
Service Provider注册表 + 策略(创建型)集中注册绑定,将"如何创建"与"何时创建"分离

注意:Laravel 将其静态代理类命名为"Facade",与 GoF Facade 模式同名,实际上两者意图不同。详见题目《Laravel Facade 命名陷阱》。

识别规律总结

  1. 找"谁在创建对象" → 创建型(服务容器、Service Provider)
  2. 找"谁在包裹/转发调用" → 结构型(Facades、Cache/Queue Driver 适配器)
  3. 找"谁在通知谁" → 行为型·观察者(Eloquent Event/Observer)
  4. 找"控制权如何传递" → 行为型·责任链(Pipeline 中间件)
  5. 找"遍历怎么封装" → 行为型·迭代器(Collection)

考察意图

考查候选人能否将框架的日常使用经验与 GoF 模式词汇体系挂钩,判断其是否具备"在实际代码中识别模式"的能力,而非只会背抽象定义。

追问链

  1. Eloquent Observer 和 Laravel Event/Listener 都是观察者模式,两者有什么区别?
    Eloquent Observer 专用于模型生命周期事件(creating/created/updating/deleted 等),与模型类强绑定;Event/Listener 是通用发布-订阅系统,事件对象可携带任意数据,支持队列异步处理。前者是后者面向 ORM 场景的语法糖。

  2. Cache 的 redis/file/database Driver 为什么是适配器模式而非策略模式?
    适配器的意图是"将已有的不兼容接口转换为目标接口"——Redis、File、Database 本身的 API 各不相同,Laravel 用 Driver 适配层统一为 Cache::get/put/forget。策略模式则强调算法族可相互替换,侧重行为变化而非接口兼容。两者外观相似但意图不同。

  3. Service Provider 的 register()boot() 分别对应什么职责,体现了什么原则?
    register() 只负责向容器写绑定("告诉容器怎么创建"),boot() 在所有 Provider 注册完成后才执行("使用已注册的服务")。职责拆分体现了单一职责原则(SRP),同时避免了 register() 阶段因依赖顺序不确定而拿到未完成绑定的问题。

易错点

  1. 把 Laravel Facade 等同于 GoF 门面模式:两者同名但意图不同。Laravel Facade 的核心机制是 __callStatic + 服务容器,是静态代理;GoF 门面是为复杂子系统提供简化接口。Laravel Facade 类同时兼具两种特征,但"静态代理"才是其实现机制的准确描述。

  2. 把 Pipeline 当成装饰器:装饰器是结构型,在不修改原对象的前提下叠加职责,通常包裹同一个对象;责任链是行为型,请求在链上流转,每个节点可终止或继续传递。Pipeline 的 $next($request) 是传递控制权而非叠加装饰,属责任链变体。

  3. 认为一个框架特性只能对应一个模式:框架实现往往是多模式的组合。例如 Laravel 的 Queue 系统同时使用了适配器(多 Driver)、命令(Job 封装操作)和模板方法(handle() 是算法骨架)。

代码示例

php
// 观察者:Eloquent Observer 与通用 Event/Listener 对比

// 方式一:Eloquent Observer(与模型绑定,覆盖生命周期事件)
class UserObserver
{
    public function created(User $user): void
    {
        // 模型创建后触发(等同于监听 eloquent.created:App\Models\User)
        Log::info("User {$user->id} created");
    }
}
// AppServiceProvider::boot() 中注册:
// User::observe(UserObserver::class);

// 方式二:通用 Event/Listener(与模型解耦,可携带任意载荷,支持队列)
class UserRegistered
{
    public function __construct(public readonly User $user) {}
}

class SendWelcomeEmail implements ShouldQueue
{
    public function handle(UserRegistered $event): void
    {
        Mail::to($event->user)->send(new WelcomeMail());
    }
}
// 触发:event(new UserRegistered($user));

基于 Apache License 2.0 开源