Last active
January 17, 2022 14:56
-
-
Save Neo42/f3e9beae4f57ed9e118a1ed2f59fa9f9 to your computer and use it in GitHub Desktop.
Design patterns in JavaScript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class OrderManager { | |
orders = new Set() | |
execute(command, ...args) { | |
return command.run(this.orders, ...args) | |
} | |
} | |
class Command { | |
constructor(steps) { | |
this.run = steps | |
} | |
} | |
function PlaceOrderCommand(order, id) { | |
return new Command((orders) => { | |
orders.add({id, order}) | |
console.log(`You have successfully ordered ${order} (${id}).`) | |
}) | |
} | |
function CancelOrderCommand(id) { | |
return new Command((orders) => { | |
orders.delete(id) | |
console.log(`You have canceled your order ${id}.`) | |
}) | |
} | |
function TrackOrderCommand(id) { | |
return new Command(() => { | |
console.log(`Your order will ${id} will arrive in 20 minutes.`) | |
}) | |
} | |
const manager = new OrderManager() | |
manager.execute(new PlaceOrderCommand('Pad Thai', 1234)) // You have successfully ordered Pad Thai (1234). | |
manager.execute(new TrackOrderCommand(1234)) // Your order will 1234 will arrive in 20 minutes. | |
manager.execute(new CancelOrderCommand(1234)) // You have canceled your order 1234. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Chatroom { | |
logMessage(user, message) { | |
const sender = user.getName() | |
console.log(`${new Date().toLocaleString()} [${sender}]: ${message}`) | |
} | |
} | |
class User { | |
constructor(name, chatroom) { | |
this.name = name | |
this.chatroom = chatroom | |
} | |
getName() { | |
return this.name | |
} | |
send(message) { | |
this.chatroom.logMessage(this, message) | |
} | |
} | |
const chatroom = new Chatroom() | |
const user1 = new User('Hao', chatroom) | |
const user2 = new User('John', chatroom) | |
user1.send('Hello') // 1/17/2022, 6:51:44 PM [Hao]: Hello | |
user2.send('Hi') // 1/17/2022, 6:52:02 PM [John]: Hi |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Dog { | |
constructor(name) { | |
this.name = name | |
} | |
} | |
const dogFunctionality = { | |
bark: () => console.log('Woof!'), | |
wagTail: () => console.log('Wagging my tail!'), | |
play: () => console.log('Playing!'), | |
} | |
Object.assign(Dog.prototype, dogFunctionality) | |
const pet1 = new Dog('Daisy') | |
pet1.name // Daisy | |
pet1.bark() // Woof! | |
pet1.play() // Playing! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Observable { | |
observers = new Set() | |
subscribe(observer) { | |
this.observers.add(observer) | |
return () => this.unsubscribe(observer) | |
} | |
unsubscribe(observer) { | |
this.observers.delete(observer) | |
console.log(`observer unsubscribed.`) | |
return this | |
} | |
publish(data) { | |
this.observers.forEach((observer) => observer?.(data)) | |
} | |
} | |
const observable = new Observable() | |
observable.subscribe((data) => console.log(`observer1: ${data}`)) | |
const unsubscribeObserver2 = observable.subscribe((data) => { | |
console.log(`observer2: ${data}`) | |
}) | |
observable.publish('Holy 💩') | |
// observer1: Holy 💩 | |
// observer2: Holy 💩 | |
unsubscribeObserver2() // observer unsubscribed. | |
observable.publish('observer2 is gone.') // observer1: observer2 is gone. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const person = { | |
name: 'hao', | |
age: 26, | |
gender: 'male', | |
} | |
// use Reflect instead of obj[prop] | |
const personProxy = new Proxy(person, { | |
get(obj, prop) { | |
console.log(`hao's gender is ${Reflect.get(obj, prop)}.`) | |
}, | |
set(obj, prop, value) { | |
if (prop === 'age') { | |
console.error(`you can't go back in time.`) | |
return | |
} | |
console.log(`changing ${obj.name}'s ${prop} to ${value}.`) | |
Reflect.set(obj, prop) | |
}, | |
}) | |
personProxy.gender // hao's gender is male. | |
personProxy.age = 18 // can't go back in time | |
personProxy.age // hao's gender is 26. | |
// use cases: validation, formatting, notifications, or debugging. | |
// downsides: performance |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// singleton: classes can be only instantiated once | |
let instance = null | |
class Counter { | |
constructor() { | |
if (instance) { | |
throw new Error('Only one instance of Counter is allowed.') | |
} | |
instance = this | |
this.count = 0 | |
} | |
getInstance() { | |
return this | |
} | |
getCount() { | |
return this.count | |
} | |
increment() { | |
return ++this.count | |
} | |
decrement() { | |
return --this.count | |
} | |
} | |
const c1 = new Counter() | |
// const c2 = new Counter() // error | |
Object.freeze(c1) // prevent from being modified | |
export default c1 | |
// downsides | |
// 1. overkill: Objects are passed through reference in JavaScript | |
// 2. hard to test: order is important | |
// 3. dependency hiding: can be easily modified and cause unexpected behaviors | |
// 4. global behavior: commonly used in state management, has to be done right |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment