05-Observer Pattern 观察者模式-vanilla篇

通过观察者模式,我们可以将某些对象(观察者)订阅到另一个称为可观察对象的对象。每当事件发生时,可观察者都会通知其所有观察者。 一个可观察对象通常包含 3 个重要部分: observers :观察者数组,每当特定事件发生时都会收到通知 subscribe() :将观察者添加到观察者列表的方法 unsubscribe() :从观察者列表中删除观察者的方法 notify() :每当特定事件发生时通知所有观察者的方法 创建一个简单的方法是使用 ES6 类。 class Observable { constructor() { this.observers = []; } subscribe(func) { this.observers.push(func); } unsubscribe(func) { this.observers = this.observers.filter((observer) => observer !== func); } notify(data) { this.observers.forEach((observer) => observer(data)); } } 我们现在可以使用 subscribe 方法将观察者添加到观察者列表中,使用 unsubscribe 方法删除观察者,并使用 notify 方法通知所有订阅者。 现在我们有一个非常基本的应用程序,仅包含两个组件: Button 和 Switch 。 export default function App() { return ( <div className="App"> <Button>Click me!</Button> <FormControlLabel control={<Switch />} /> </div> ); } 我们希望跟踪用户与应用程序的交互。每当用户单击按钮或切换开关时,我们都希望使用时间戳记录此事件。除了记录之外,我们还想创建一个 Toast 通知,每当事件发生时就会显示。...

August 5, 2023 · 2 min · 379 words · Anna.me

04-Mixin Pattern 混合模式-vanilla篇

mixin 是一个对象,我们可以使用它向另一个对象或类添加可重用的功能,而无需使用继承。我们不能单独使用 mixin:它们的唯一目的是在没有继承的情况下向对象或类添加功能。 假设我们的应用程序需要创建多只狗。然而,我们创建的基本狗除了 name 属性之外没有任何属性。 class Dog { constructor(name) { this.name = name; } } 狗应该能够做的不仅仅是有名字。它应该能够吠叫、摇尾巴和玩耍!我们可以创建一个 mixin 来为我们提供 bark 、 wagTail 和 play 属性,而不是直接将其添加到 Dog 中。 const dogFunctionality = { bark: () => console.log("Woof!"), wagTail: () => console.log("Wagging my tail!"), play: () => console.log("Playing!"), }; 我们可以使用 Object.assign 方法将 dogFunctionality mixin 添加到 Dog 原型中。此方法允许我们向目标对象添加属性:在本例中为 Dog.prototype 。 Dog 的每个新实例都可以访问 dogFunctionality 的属性,因为它们被添加到 Dog 的原型中。 class Dog { constructor(name) { this.name = name; } } const dogFunctionality = { bark: () => console....

August 4, 2023 · 2 min · 298 words · Anna.me

03-Mediator/Middleware Pattern 中介者/中间件模式-vanilla篇

中介者模式使组件可以通过一个中心点(中介者)相互交互。中介者不是直接相互交谈,而是接收请求并将其转发。在 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....

August 2, 2023 · 1 min · 160 words · Anna.me

01-Command Pattern 命令模式-vanilla篇

使用命令模式,可以将执行某个任务的对象与调用该方法的对象解耦。 假设有一个外卖配送平台。用户可以下单、跟踪和取消订单。 class OrderManager() { constructor() { this.orders = [] } placeOrder(order, id) { this.orders.push(id) return `You have successfully ordered ${order} (${id})`; } trackOrder(id) { return `Your order ${id} will arrive in 20 minutes.` } cancelOrder(id) { this.orders = this.orders.filter(order => order.id !== id) return `You have canceled your order ${id}` } } 在 OrderManager 类上,可以访问 placeOrder 、 trackOrder 和 cancelOrder 方法。直接使用这些方法将是完全可行的。 但是,直接在 manager 实例上调用方法也有缺点。我们可能会决定稍后重命名某些方法,或者改变某些方法的功能。 假设现在将其重命名为 addOrder ,而不是 placeOrder ,这意味着我们必须确保代码库中的没有任何位置调用 placeOrder 方法,这种场景在大型应用程序中可能非常棘手。相反,我们希望将方法与 manager 对象解耦,并为每个命令创建单独的命令函数。...

July 12, 2023 · 1 min · 195 words · Anna.me

02-Factory Pattern 工厂模式-vanilla篇

通过工厂模式,我们可以使用工厂函数来创建新对象。当一个函数不使用 new 关键字来返回一个新对象时,它就是一个工厂函数。 假设我们的应用程序需要许多用户。我们可以使用 firstName 、 lastName 和 email 属性创建新用户。工厂函数还将 fullName 属性添加到新创建的对象中,该属性返回 firstName 和 lastName 。 const createUser = ({ firstName, lastName, email }) => ({ firstName, lastName, email, fullName() { return `${this.firstName} ${this.lastName}`; }, }); 现在我们可以通过调用 createUser 函数轻松创建多个用户。 const user1 = createUser({ firstName: "Anna", lastName: "Cheng", email: "AnnaCheng@gmail.com", }); 如果我们要创建相对复杂且可配置的对象,工厂模式会很有用。键和值的值可能取决于特定的环境或配置。使用工厂模式,我们可以轻松创建包含自定义键和值的新对象。 const createObjectFromArray = ([key, value]) => ({ [key]: value, }); createObjectFromArray(["name", "John"]); // { name: "John" } 优点 当我们必须创建多个共享相同属性的较小对象时,工厂模式非常有用。工厂函数可以根据当前环境或用户特定的配置轻松返回自定义对象。...

1 min · 127 words · Anna.me