Laravel中策略模式是开发者自主实现的设计模式,非框架内置;适用于多变且差异大的业务逻辑(如支付方式、地区定价),需定义接口、绑定实现并动态解析,避免滥用。

“策略”在 Laravel 里不是框架内置的抽象概念,也没有叫 Strategy 的核心类或命令;它是一种设计模式的落地实践,靠开发者自己组织结构、接口和运行时选择来实现——用错地方反而增加复杂度。
什么时候该手写策略模式,而不是用 Laravel 自带机制
别一上来就建 app/Strategies 目录。先确认是否真需要策略:比如支付方式(支付宝/微信/银行卡)要动态切换逻辑,且每种处理流程差异大、未来可能新增;又或者不同地区用户的价格计算规则完全不同。
- 如果只是简单 if-else 分支,直接写在服务类里更清晰
- 如果只是配置开关(如
'payment_method' => 'alipay'),用 config + 条件调用就行,不用抽象成类 - 如果逻辑差异只在数据库字段或 API 地址,优先考虑模型属性或配置驱动,而非策略类
如何定义可被容器自动解析的策略接口与实现
关键不是“怎么写策略”,而是“怎么让 Laravel 容器知道该用哪一个”。推荐用接口 + 绑定 + 运行时解析的组合:
- 定义统一接口:
app/Contracts/PaymentStrategy.php,声明process(array $data): bool - 每个实现类(如
AlipayStrategy、WechatStrategy)都实现该接口 - 在
AppServiceProvider::register()中绑定具体实现:$this->app->bind(PaymentStrategy::class, fn() => new AlipayStrategy());,但注意:这只能绑定一个默认实现 - 真正需要多实例时,用容器标签或工厂闭包:
$this->app->when(OrderService::class)->needs(PaymentStrategy::class)->give(function ($app, $parameters) { return $app->make($parameters['driver'] . 'Strategy'); });
这样 OrderService 构造时传入 ['driver' => 'wechat'],就能动态解析对应策略。
避免把策略模式和路由模型绑定、Policy 混为一谈
新手常误以为 Route::model('user', User::class) 或 Gate::define('update', ...) 是“策略”。它们不是:
Laravel Cloud(cloud.laravel.com)。此技能用于处理所有 Laravel Cloud 请求,包括搜索和读取数据。只要任务涉及 Laravel Cloud,即使用此技能。
-
Route::model()是自动注入,不涉及行为分支选择 -
Policy是授权判断,返回 true/false,不封装业务流程 - 真正的策略模式必须有多个**可互换的、完整的行为实现体**,且由外部决定用哪一个
比如你写了 UserDeletionStrategy 和 UserArchivingStrategy,但整个系统只调用其中一种且永不切换,那它只是个普通服务类,不是策略。
策略类里别偷偷依赖请求、session 或 DB 连接
策略应是无状态、纯逻辑的。常见翻车点:
- 在策略方法里直接调用
request()->ip()—— 应由上层把 IP 当参数传入 - 用
DB::transaction()包裹操作 —— 事务边界应在调用方(如控制器或领域服务)控制 - 读取
config('app.debug')做分支 —— 配置差异应提前映射为策略类型,而非运行时查配置
策略越“瘦”,越容易单元测试、复用和替换。真正复杂的上下文数据,应该通过构造函数注入依赖,或由调用方以参数形式传递。
策略模式的价值不在“用了设计模式”,而在“当第三种支付渠道上线时,你只需加一个类、改一处绑定,而不用动已有二十处 if-else”。没到那个量级前,先写清楚再重构,比提前抽象更可靠。

















