中介者模式使得组件通过一个中心点——中介者进行交互。组件不需要直接进行通信,而是将请求发送给中介者,由中介者进行转发!在JavaScript中,中介者往往只是一个对象字面量或一个函数。
你可以将这种模式与空中交通管制员和飞行员之间的关系进行比较。飞行员不是直接互相交谈,这可能会相当混乱,而是与空中交通管制员交谈。空中交通管制员确保所有飞机接收到他们所需的信息,以便安全飞行,不与其他飞机相撞。
虽然我们希望不要使用 JavaScript 控制飞机,但我们往往不得不处理对象之间的多向数据。如果组件数量庞大,那么组件之间的通信会变得相当复杂。
对象的请求由中介处理,而不是让每个对象直接与其他对象通信,从而产生多对多关系。调解器处理此请求,并将其转发到需要的位置。
中介模式的一个很好的用例是聊天室!聊天室中的用户不会直接相互交谈。相反,聊天室充当用户之间的中介人。
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
方法调用请求-响应周期中的下一个回调。我们实际上是在创建位于请求和响应之间的中间件函数链,反之亦然。
让我们添加另一个中间件函数来检查是否正确添加了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();
}
);
我们可以通过一个或多个中间件函数跟踪和修改请求对象,一直到响应。
const app = require("express")();
const html = require("./data");
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");
});
每次用户点击根端点 '/'
时,都会调用两个中间件回调。
中介器模式通过让所有通信都流经一个中心点,使我们能够轻松地简化对象之间的多对多关系。