學習 Laravel 框架過程中很常可以看到所有的檔案都是 class,而且非常看重物件導向,其中依賴注入和繼承最常見;前端呢?今天來談談我所了解的 JavaScript 設計模式!
👍🏻👍🏻👍🏻 推薦好片:淺談 Javascript 設計模式 | Alex 宅幹嘛
回顧過去:第 16 天:建構子函數 - OOPs
參考文章:【翻譯】JavaScript 設計模式、javascript设计模式【上】、javascript设计模式【下】
設計模式是經過驗證的解決方案,用於解決在軟體設計中常見的問題,另外也可以提高代碼的可讀性、可維護性和重用性。
找到的文章中主要對模組模式、原型模式、代理模式、觀察者模式、工廠模式比較有感覺,回想起來似乎自己就有用到,所以對於這幾個設計模式說明。
模組模式 Module Pattern
模組模式用於封裝代碼,提供私有和公有接口,避免全局命名衝突。
const Module = (function () {
// 私有變數 -> 在 module 外部不能被訪問,確保資料封裝
let privateVar = "私人";
return {
// 可以存取斯有變數的功用函數
publicMethod: function () {
console.log(privateVar);
},
setPrivateVar: function (value) {
privateVar = value;
}
};
})();
Module.publicMethod(); // "私人"
Module.setPrivateVar("New value");
Module.publicMethod(); // "New value"
原型模式 Prototype Pattern
原型模式基於原型鏈來創建對象,允許對象共享屬性和方法,從而節省內存。
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function () {
console.log(`Hello, my name is ${this.name}`);
};
const kuku = new Person("kuku");
const ting = new Person("ting");
kuku.sayHello(); // "Hello, my name is kuku"
ting.sayHello(); // "Hello, my name is ting"
代理模式 Proxy Pattern
代理模式提供了一個替代物件,通過該物件來控制對其他物件的訪問。
const RealSubject = {
request: function () {
console.log("Request processed");
}
};
const Proxy = (function () {
return {
request: function () {
console.log("Logging: Before request");
RealSubject.request();
console.log("Logging: After request");
}
};
})();
Proxy.request();
🔔 Proxy 代理是什麼!?
Proxy 物件允許在物件上的基本操作建立自訂行為,如屬性查找、賦值、枚舉 enum、函數呼叫等...
const target = {
message1: "Hello",
message2: "World"
};
const handler = {
get: function (target, prop, receiver) {
console.log(`Property '${prop}' was accessed.`);
return Reflect.get(...arguments);
}
};
const proxy = new Proxy(target, handler);
console.log(proxy.message1); // Logs: Property 'message1' was accessed. console.log(proxy.message2); // Logs: Property 'message2' was accessed.
觀察者模式
觀察者模式定義了一種一對多的依賴關係,使得當一個對象的狀態改變時,所有依賴於它的對象都會得到通知並自動更新。
function Subject() {
this.observers = [];
this.addObserver = function (observer) {
this.observers.push(observer);
};
this.notifyObservers = function (data) {
this.observers.forEach((observer) => observer.update(data));
};
}
function Observer(name) {
this.name = name;
this.update = function (data) {
console.log(`${this.name} received data: ${data}`);
};
}
const subject = new Subject();
const observer1 = new Observer('Observer 1');
const observer2 = new Observer('Observer 2');
subject.addObserver(observer1);
subject.addObserver(observer2);
subject.notifyObservers('Hello, Observers!');
// 輸出:
// Observer 1 received data: Hello, Observers!
// Observer 2 received data: Hello, Observers!
class Subject {
constructor() {
this.observers = [];
}
addObserver(observer) {
this.observers.push(observer);
}
notifyObservers() {
this.observers.forEach(observer => observer.update());
}
}
💡 這種模式就很像 Vue 的 Vuex
和 Pinia
,這類的狀態管理或事件處理,只要狀態改變,所有依賴的都會一起改變!
工廠模式
回顧一下:第 18 天:閉包與作用域
工廠模式是一種創建對象的模式,使用工廠方法來創建對象,而不是直接使用 new
,這樣可以將對象的創建過程封裝起來,並提高代碼的可擴展性和可維護性。
function Car(make, model) {
this.make = make;
this.model = model;
}
function CarFactory() {
this.createCar = function (make, model) {
return new Car(make, model);
};
}
const factory = new CarFactory();
const car1 = factory.createCar('Toyota', 'Corolla');
const car2 = factory.createCar('Honda', 'Civic');
console.log(car1); // Car { make: 'Toyota', model: 'Corolla' }
console.log(car2); // Car { make: 'Honda', model: 'Civic' }