設(shè)計模式:是一種抽象的編程思想,并不局限于某一特定的編程語言,而是在許多語言之間是相通的;它是軟件設(shè)計中常見的問題的通用、可反復(fù)使用、多少人知曉的一種解決方案或者模板。一般對與從事過面向?qū)ο缶幊痰娜藖碚f會更熟悉一些。
設(shè)計模式的意義:指導(dǎo)我們?nèi)绾螌懗隹删S護(hù)、可復(fù)用、可擴(kuò)展及靈活的代碼。
接下來我們來簡單了解一下前端開發(fā)過程中的一些常用的設(shè)計模式。
1.單例模式
使用場景
當(dāng)需要一個對象去貫穿整個應(yīng)用系統(tǒng)中,且這個對象中的數(shù)據(jù)是系統(tǒng)中全局共享的。比如,Vue 中的 Vuex 中的 store。
實現(xiàn)方式
通過隱藏指定的Class 構(gòu)造函數(shù)來創(chuàng)建或獲取唯一實例的一種實現(xiàn)方式;
使用閉包保存局部作用域中的單例對象并返回。
const SingleInstance = (function(){
function SingleClas(){
}
let singleObj;
return {
getInstance:function(){
if(!singleObj){
singleObj = new SingleClas();
}
return singleObj;
}
}
})();
const instance1 = SingleInstance.getInstance();
const instance2 = SingleInstance.getInstance();
console.log(instance1 === instance2);//true
注意事項
因為單例模式會引入全局狀態(tài),所以應(yīng)用開發(fā)過程中盡量避免大量的單例模式的使用。
2. 發(fā)布-訂閱模式(有的叫消息隊列模式)
思想:
在發(fā)布-訂閱模式中,有兩種類型的對象:
- 發(fā)布者: 是事件的發(fā)出者,通常維護(hù)一個事件列表,并且可以向列表中添加或者刪除事件;當(dāng)某個事件發(fā)生時,將這個事件通知給所有的訂閱者。
- 訂閱者:是事件的接收者,它們訂閱了某個事件,并且在這個事件發(fā)生時接收對應(yīng)的通知。
使用場景
他是一種將發(fā)布者和訂閱者解耦的設(shè)計模式,在前端開發(fā)中,可以使用該模式實現(xiàn)組件之間的通信。這個模式應(yīng)該是我們平時接觸的最多的了,JavaScript 中的事件訂閱響應(yīng)機(jī)制。比如 Vue 中的 事件總線
實現(xiàn)方式
//定義一個發(fā)布者
let publisher = {
let events:{},//定義一個對象,用來存放事件列表
//定義添加事件的方法,添加到事件列表中
addEvent(event,callback){
if(!events[event]){
this.events[event] =[];
}
this.events[event].push(callback);
},
//定義刪除事件的方法
removeEvent(event,callback){
if(this.events[event]){
for(let i = 0;i<this.events[event].length; i++){
if(this.events[event][i] === callback){
this.events[event].splice(i,1);
break;
}
}
}
},
//發(fā)布事件
publishEvent(event,data){
if(this.events[event]){
for(let i=0;i < this.events[event].length; i ++){
this.events[event][i](data);
}
}
}
};
//定義一個訂閱者
let subscriber1 = {
//處理事件回調(diào)
handleEvent(data){
//...這里處理data操作
}
};
//訂閱事件
publisher.addEvent('event1',subscriber1.handleEvent);
//發(fā)布事件
publisher.publishEvent('event','Hi event1 happend');
//取消訂閱
publisher.removeEvent('event1',subscriber1.handleEvent);
3. 觀察者模式 ‘等效于’ 發(fā)布-訂閱模式
使用場景
該模式跟發(fā)布訂閱模式有點(diǎn)像,有很多地方把這個模式等同于發(fā)布-訂閱模式。
當(dāng)對象間存在一對多的依賴關(guān)系時,可以使用觀察者模式,當(dāng)被觀察的對象發(fā)生變化時,其所有的觀察者都會收到通知并進(jìn)行相應(yīng)的操作。在 javascript 中可以使用回調(diào)函數(shù)或者事件監(jiān)聽來實現(xiàn)觀察者模式。觀察者模式通常被用來實現(xiàn)組件間的數(shù)據(jù)傳遞和事件處理。比如 React 中的 Redux 和事件處理庫 EventEmitter
實現(xiàn)方式
- 定一個被觀察對象 Subject,當(dāng)其發(fā)生改變時通知所有的觀察者;
- 定義觀察者 Observer ,是觀察被觀察對象的對象,當(dāng)Subject 發(fā)生改變時,會接收到通知并進(jìn)行相應(yīng)的處理。
class Subject{
constructor(){ this.observers =[];}
addObserver(observer){this.observers.push(observer);}
removeObserver(observer){
this.observers = this.observer.filter(ob => ob !== observer);
}
notify(data){this.observers.forEach(ob => ob.update(data));}
}
class Observer{
update(data){
//...這里處理回調(diào)邏輯
console.log(data+'data發(fā)生改變了');
}
}
const subject = new Subject();
const ob1 = new Observer();
const ob2 = new Observer();
subject.addObserver(ob1);
subject.addObserver(ob2);
subject.notify('wow');
//wow data發(fā)生改變了
//wow data發(fā)生改變了
4. 裝飾者模式
使用場景
動態(tài)的給一個對象或者組件添加額外的行為或樣式??梢宰屛以诓桓淖冊写a的情況下給組件添加新的行為和樣式。這也是‘裝飾’一詞的由來,不改變原有的,繼續(xù)往上添加行為或樣式。
實現(xiàn)方式
方式一:通過擴(kuò)展對象的屬性或者方法實現(xiàn)
//原始對象
const obj = {
f1(){console.log("我是 f1");}
}
//創(chuàng)建一個裝飾函數(shù),擴(kuò)展 obj 的方法
const decoratorFn=(obj)=>{
obj.f2 = ()=>{console.log("我是 f2");}
return obj;
}
const decObj = decoratorFn(obj);//裝飾 obj
decObj.f1();//我是 f1
decObj.f2();//我是 f2
方式二:通過擴(kuò)展對象的原型來實現(xiàn)
//定義一個原始對象
function F1(){}
//在對象的原向上定義一個方法
F1.prototype.f1 = ()=>{console.log("我是 f1");}
//定義一個裝飾函數(shù)
const decoratorFn=(clazz)=>{
clazz.prototype.f2= ()=>{console.log("我是 f2");}
}
//使用裝飾器函數(shù)擴(kuò)展原型
decoratorFn(F1);
const obj = new F1();
obj.f1();//我是 f1
obj.f2();//我是 f2
5. 代理模式
思想:
為一個對象提供一個替代品或者是占位符,以便控制對它的訪問。在前端開發(fā)中該模式經(jīng)常被用來處理一些復(fù)雜或者耗時的操作,它通過引入一個代理對象來控制對原是對象的訪問,這個代理對象類似于原始對象的中介,客戶跟中介交互,中介再跟原始對象交互。有的地方也叫 “中介者模式”。
比如:圖片的懶加載、緩存等。
實現(xiàn)方式
//我們第一個原始的 image 對象
class Image{
constructor(url){
this.url = url;
}
//定義加載圖片的方法
load(){
console.log('加載圖片')
}
}
//定義一個代理對象 實現(xiàn)延遲加載圖片
class ProxyImage{
constructor(url){
this.url = url;
this.image = null;
}
//定義加載圖片的方法
load(){
if(!this.image){
this.image = new Image(this.url)
console.log('延遲加載');//可以使用占位符代替
}
this.image.load();//加載圖片
}
}
const img1 = new ProxyImage('http://...img1.png');
const img2 = new ProxyImage('http://...img2.png');
img1.load();//延遲加載, 加載圖片
img1.load();//加載圖片
img2.load();//延遲加載 加載圖片
上述的實現(xiàn)方式,如果圖片已經(jīng)被加載過了,代理對象就會直接顯示圖片,否則代理對象會加載占位符,并延遲加載,如果已經(jīng)加載過了,代理對象就直接顯示圖片。通過這種模式就可以在不影響原始對象的情況下,實現(xiàn)圖片的懶加載。文章來源:http://www.zghlxwxcb.cn/news/detail-820495.html
除了以上的模式,常見的還有 【工廠模式】、【迭代器模式】、【策略模式】等,由于篇幅有限,后續(xù)再補(bǔ)上。文章來源地址http://www.zghlxwxcb.cn/news/detail-820495.html
到了這里,關(guān)于前端常用的設(shè)計模式的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!