文档目录
服务层设计模式

简介

本文件聚焦 DouPHP 框架服务层的设计模式与架构实践,围绕策略、工厂、观察者、单例等模式在服务层的落地方式展开。通过“薄编排门面 + 主题域子服务”的组合,配合轻量级依赖注入容器与事件系统,实现高内聚、低耦合、可扩展、可测试的服务层体系。文档同时给出关键流程的可视化图示与定位到源码的引用路径,便于读者快速理解并应用到实际业务中。

项目结构

DouPHP 的服务层按领域划分,核心服务位于 core/service,各端(admin/front/api)也有各自的服务层;基础能力集中在 core/foundation,包括依赖注入容器与事件系统。服务类普遍继承 BaseService,并通过构造函数注入细粒度子服务,形成稳定的对外门面。

graph TB
subgraph "核心服务"
BS["BaseService"]
US["UserService"]
OS["OrderService"]
end
subgraph "领域子服务"
UQ1["UserProfileQuery"]
UQ2["UserMembershipQuery"]
UQ3["UserContactQuery"]
UP["UserPromotionService"]
OC["OrderCartQuery"]
OST["OrderStatusTransition"]
OI["OrderItemQuery"]
OG["OrderStockGuard"]
OT["OrderScheduledTasks"]
OO["OrderCheckoutOptions"]
end
subgraph "基础设施"
C["Container(依赖注入)"]
E["Event(事件)"]
end
US --> UQ1
US --> UQ2
US --> UQ3
US --> UP
OS --> OC
OS --> OST
OS --> OI
OS --> OG
OS --> OT
OS --> OO
BS --> C
BS --> E

核心组件

  • 服务基类 BaseService:定义服务通用约定与依赖获取方式(通过 helper/门面就近解析),不直接持有 ORM Model 实例,写操作统一走静态门面,读操作使用 with() 关联查询。
  • 用户服务 UserService:作为薄编排门面,组合资料读取、扩展身份、联系人、推广关系等子服务,对外提供稳定方法签名。
  • 订单服务 OrderService:作为薄编排门面,组合购物车、状态机、条目视图、库存守卫、定时任务、结算选项等子服务,封装订单相关复杂流程。
  • 依赖注入容器 Container:支持绑定、单例、工厂闭包、上下文绑定、别名、自动构造注入、调用时参数注入、重置隔离等能力。
  • 事件系统 Event/SystemEvents:提供事件注册与触发机制,用于解耦横切关注点(如支付成功后的积分、分销、会员升级联动)。

架构总览

服务层采用“门面 + 子服务”的组合模式,结合 DI 容器进行依赖装配,通过事件系统解耦副作用处理。整体遵循单一职责原则,将变化原因收敛到具体子服务中,门面保持稳定接口。

sequenceDiagram
participant Caller as "调用方"
participant Service as "OrderService"
participant Transition as "OrderStatusTransition"
participant Stock as "OrderStockGuard"
participant Tasks as "OrderScheduledTasks"
participant Events as "Event"
Caller->>Service : changeStatus(order_sn, new_status)
Service->>Transition : changeStatus(order_sn, new_status)
Transition->>Stock : checkStock(module, item_id, number)
Stock-->>Transition : 校验结果
Transition->>Transition : 更新订单状态/付款联动
Transition->>Tasks : 调度后续任务(评价/取消等)
Transition->>Events : 触发事件(如支付完成)
Events-->>Caller : 异步副作用执行完毕
Service-->>Caller : 返回结果

详细组件分析

服务基类 BaseService 与设计模式映射

  • 单例模式:全局容器以静态单例形式提供,保证应用级唯一性。
  • 工厂模式:容器支持工厂闭包绑定,按需创建对象。
  • 策略模式:通过上下文绑定或模块开关,在不同场景选择不同实现(例如支付方式、配送方式插件列表)。
  • 观察者模式:事件系统用于发布-订阅,解耦副作用逻辑。

用户服务 UserService:门面编排与依赖注入

UserService 通过构造函数注入多个子服务,将“资料查询、扩展身份、联系人、推广关系”等能力聚合为统一入口,屏蔽内部复杂度。

classDiagram
class BaseService
class UserService {
- profileQuery
- membershipQuery
- contactQuery
- promotionService
+ buildUserProfile(row, field)
+ levelName(level_id)
+ findUserId(keyword)
+ currentLevel(userId)
+ format(userOrId)
+ work(user_id)
+ vip(user_id)
+ distribution(user_id)
+ isVip(userId)
+ isWork(userId)
+ isDistribution(userId)
+ contactList(user_id, current_contact_id)
+ addressFull(contact)
+ resolvePromotionLineage(userSn, selfUserId)
+ recordPromotionRelation(newUserId, directUserId)
+ randUserSn()
+ createAvatarFilename()
}
class UserProfileQuery
class UserMembershipQuery
class UserContactQuery
class UserPromotionService
BaseService <|-- UserService
UserService --> UserProfileQuery : "组合"
UserService --> UserMembershipQuery : "组合"
UserService --> UserContactQuery : "组合"
UserService --> UserPromotionService : "组合"

订单服务 OrderService:状态机与库存守卫

OrderService 将订单状态变更、库存校验、结算选项、定时任务等拆分为独立子服务,通过门面统一暴露。

flowchart TD
Start(["进入 changeStatus"]) --> CheckStock["调用库存守卫检查库存"]
CheckStock --> StockOK{"库存是否充足?"}
StockOK -- 否 --> Fail["返回失败/提示"]
StockOK -- 是 --> UpdateStatus["更新订单状态/记录支付方式"]
UpdateStatus --> TriggerEvents["触发事件(支付完成/分销奖励等)"]
TriggerEvents --> ScheduleTasks["调度定时任务(自动评价/取消)"]
ScheduleTasks --> End(["返回成功"])

依赖注入容器 Container:工厂、单例、上下文绑定

Container 提供轻量级 DI 能力,支持:

  • 绑定抽象到具体类(含别名)
  • 单例注册与实例直注
  • 工厂闭包绑定
  • 上下文绑定 when()->needs()->give()
  • 反射自动注入构造函数依赖与方法参数依赖
  • 状态查询 has/bound/resolved 与 reset 重置(测试隔离)
sequenceDiagram
participant App as "应用启动"
participant C as "Container"
participant Svc as "OrderService"
participant Sub as "OrderStatusTransition"
App->>C : singleton("order.status", "OrderStatusTransition")
App->>C : make("OrderService")
C->>C : 反射解析构造函数依赖
C->>Sub : 解析并注入子服务
C-->>App : 返回已装配的 OrderService
App->>Svc : 调用业务方法
Svc->>Sub : 委托状态变更
Sub-->>Svc : 返回结果

事件驱动架构:观察者模式的应用

事件系统用于在关键业务节点发布事件,订阅者处理副作用(如积分、分销、会员升级)。该模式降低主流程与副作用之间的耦合度,提升可测试性与可维护性。

sequenceDiagram
participant Biz as "业务服务(OrderService)"
participant Ev as "Event"
participant Sub1 as "订阅者A(积分)"
participant Sub2 as "订阅者B(分销)"
participant Sub3 as "订阅者C(会员升级)"
Biz->>Ev : 触发事件("订单支付完成")
Ev-->>Sub1 : 通知订阅者A
Ev-->>Sub2 : 通知订阅者B
Ev-->>Sub3 : 通知订阅者C
Sub1-->>Biz : 副作用完成
Sub2-->>Biz : 副作用完成
Sub3-->>Biz : 副作用完成

策略模式:支付方式与配送方式的动态选择

通过容器上下文绑定或模块开关,可在运行时选择不同策略实现(如多种支付方式、配送方式)。OrderService 的结算选项子服务负责列出启用的插件,体现策略的可插拔特性。

工厂模式:容器工厂闭包与按需创建

容器支持工厂闭包绑定,适合复杂对象的构建逻辑(如带配置的对象、外部资源初始化)。工厂覆盖先前绑定,确保最新策略生效。

单例模式:全局容器与应用级共享

容器以静态单例形式提供,避免重复初始化;同时支持 instance() 直注已有实例,便于测试替换。

依赖关系分析

服务层通过 DI 容器管理依赖,服务之间松耦合,子服务可按需启用或替换。事件系统进一步解耦副作用逻辑,使主流程更清晰。

graph LR
C["Container"] --> |make/bind/singleton| Svc["OrderService / UserService"]
Svc --> |组合| Sub1["OrderStatusTransition / UserMembershipQuery"]
Svc --> |组合| Sub2["OrderStockGuard / UserContactQuery"]
Svc --> |组合| Sub3["OrderScheduledTasks / UserPromotionService"]
Svc --> |触发| Ev["Event"]
Ev --> |通知| Subs["订阅者(积分/分销/会员升级)"]

性能考量

  • 单例缓存:容器对单例进行缓存,减少重复创建开销。
  • 延迟加载:通过工厂闭包与上下文绑定,仅在需要时创建对象。
  • 事件异步化:副作用通过事件解耦,避免阻塞主流程。
  • 查询优化:服务层读操作使用 with() 预加载关联,减少 N+1 查询。

故障排查指南

  • 依赖解析失败:当容器无法解析某个参数时,会抛出包含依赖链的错误信息,便于定位缺失绑定或类型不匹配问题。
  • 上下文绑定冲突:when()->needs()->give() 仅作用于当前消费者,若出现意外影响,检查构建栈与绑定顺序。
  • 事件未触发:确认事件注册与触发位置是否正确,必要时通过 SystemEvents 常量核对事件名。
  • 单例污染:测试环境可使用 reset() 清空容器状态,避免跨用例污染。

结论

DouPHP 服务层通过“门面 + 子服务”的组合、DI 容器的依赖装配与事件系统的解耦,实现了高内聚、低耦合、可扩展、可测试的架构。策略、工厂、观察者、单例等设计模式在服务层得到系统化应用,既保证了业务稳定性,又提升了扩展与维护效率。建议在新功能开发中继续遵循此模式,将变化原因收敛到具体子服务,并通过容器与事件系统进行装配与解耦。

附录

  • 最佳实践
    • 服务保持薄编排,复杂逻辑下沉到子服务。
    • 使用容器进行依赖注入,避免硬编码依赖。
    • 通过事件处理副作用,保持主流程简洁。
    • 在测试中使用容器 reset 与上下文绑定进行隔离与替换。
  • 参考路径
    • 服务基类约定:core/service/BaseService.php:21-63
    • 用户服务门面:core/service/user/UserService.php:39-69
    • 订单服务门面:core/service/order/OrderService.php:37-79
    • 依赖注入容器:core/foundation/container/Container.php:23-33
    • 事件系统:core/foundation/event/Event.php, core/foundation/event/SystemEvents.php
添加日期:2026-10-05