中介者模式使组件可以通过一个中心点(中介者)相互交互。中介者不是直接相互交谈,而是接收请求并将其转发。在 JavaScript 中,中介者通常只不过是一个对象文字或一个函数。

可以将此模式与空中交通管制员和飞行员之间的关系进行比较。飞行员之间不会直接相互交谈(这可能会导致混乱),而是与空中交通管制员交谈。空中交通管制员确保所有飞机都能收到安全飞行所需的信息,而不会撞到其他飞机。

在 Javascript 中,我们经常需要处理对象之间的多向数据。项目中如果有大量组件,组件之间的通信很可能会变得相当混乱。

Flow

对象的请求由中介处理,而不是让每个对象直接与其他对象对话,从而形成多对多关系。中介器处理该请求,并将其转发到需要的位置。

Flow

调解者模式的一个很好的用例是聊天室。聊天室中的用户不会直接相互交谈。相反,聊天室充当用户之间的中介。

class ChatRoom {
  logMessage(user, message) {
    const time = new Date();
    const sender = user.getName();

    console.log(`${time} [${sender}]: ${message}`);
  }
}

class User {
  constructor(name, chatroom) {
    this.name = name;
    this.chatroom = chatroom;
  }

  getName() {
    return this.name;
  }

  send(message) {
    this.chatroom.logMessage(this, message);
  }
}

我们可以创建连接到聊天室的新用户。每个用户实例都有一个 send 方法,我们可以使用它来发送消息。

const chatroom = new ChatRoom();

const user1 = new User("John Doe", chatroom);
const user2 = new User("Jane Doe", chatroom);

user1.send("Hi there!");
user2.send("Hey!");

案例分析

Express.js 是一种流行的 Web 应用程序服务器框架。我们可以向用户可以访问的某些路由添加回调。

假设如果用户点击根路径 '/' ,我们希望向请求添加一个标头。我们可以在中间件回调中添加此标头。

const app = require("express")();

app.use("/", (req, res, next) => {
  req.headers["test-header"] = 1234;
  next();
});

next 方法调用请求-响应周期中的下一个回调。我们将有效地创建位于请求和响应之间的中间件功能链,反之亦然。

Flow

让我们添加另一个中间件函数来检查 test-header 是否已正确添加。之前的中间件功能添加的更改将在整个链中可见。

const app = require("express")();

app.use(
  "/",
  (req, res, next) => {
    req.headers["test-header"] = 1234;
    next();
  },
  (req, res, next) => {
    console.log(`Request has test header: ${!!req.headers["test-header"]}`);
    next();
  }
);

app.get("/", (req, res) => {
  res.set("Content-Type", "text/html");
  res.send(Buffer.from(html));
});

app.listen(8080, function () {
  console.log("Server is running on 8080");
});

我们可以通过一个或多个中间件函数跟踪和修改请求对象一直到响应。

每次用户点击根端点 '/' 时,都会调用两个中间件回调。

总结

中间件模式让所有通信都流经一个中心点,使我们能够轻松简化对象之间的多对多关系。