You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

中介者模式是否等同于服务定位器?其是否违反迪米特法则?

关于中介者模式的困惑与澄清

你的核心困惑

  • 误认为中介者模式和服务定位器(反模式)类似,只是存放对象的容器
  • 觉得重构后的代码违反迪米特法则,出现过多链式调用

中介者模式 vs 服务定位器:本质区别

你觉得两者像,是因为误用了中介者模式——你写的ModelsMediator只是单纯持有模型实例,没有承担中介者的核心职责。两者的核心差异在于:

  • 目的不同:中介者是为了协调多个对象间的复杂交互,让对象只和中介者通信,避免对象间直接耦合;服务定位器是提供全局对象查找入口,本质是隐藏依赖的全局访问点,容易导致代码难以追踪。
  • 依赖关系不同:中介者模式中,业务对象和中介者的依赖是双向且明确的,中介者封装了所有对象间的协作逻辑;服务定位器是对象主动去查找依赖,依赖关系是隐式的,调用方不知道依赖的来源。

正确的中介者模式示例

class ModelsMediator {
    private $users;
    private $userPasswords;

    public function __construct(UserModel $users, UserPasswordModel $userPasswords) {
        $this->users = $users;
        $this->userPasswords = $userPasswords;
    }

    // 封装跨模型的协作逻辑
    public function getUserWithPassword(int $userId) {
        $user = $this->users->getById($userId);
        $password = $this->userPasswords->getByUserId($userId);
        return ['user' => $user, 'password' => $password];
    }
}

class Test {
    private $mediator;

    public function __construct(ModelsMediator $mediator) {
        $this->mediator = $mediator;
    }

    public function handleUser(int $userId) {
        // 只和中介者交互,无需直接操作模型
        $userData = $this->mediator->getUserWithPassword($userId);
    }
}

这个示例里,中介者不是容器,而是交互的协调中心,业务类Test不需要知道各个模型的存在,只需要调用中介者提供的高层方法。

关于迪米特法则的误解

你提到的this.models.users.getAll()确实违反了迪米特法则——这是因为你把中介者当成了模型容器,让Test直接访问了中介者内部的对象(朋友的朋友)。

在正确的中介者模式下,Test只和ModelsMediator这个直接依赖交互,不会触及中介者内部的模型,完全符合迪米特法则的要求:只和直接朋友通信。

链式调用的问题根源

你遇到的链式调用问题,同样是误用中介者模式导致的。真正的中介者会封装所有跨对象的协作逻辑,业务类只需要调用中介者的封装方法,不会出现models.users.getAll()这种需要逐层访问的链式调用。

内容的提问来源于stack exchange,提问作者John Smith

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 22:03:31