溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

javascript常用的設(shè)計(jì)模式

發(fā)布時(shí)間:2020-09-08 09:20:40 來(lái)源:腳本之家 閱讀:133 作者:zhoujun 欄目:web開(kāi)發(fā)

js最好是一種面向?qū)ο蟮恼Z(yǔ)言。它的出現(xiàn)時(shí)比較遲的。但是它是目前最火的腳本語(yǔ)言。而且,隨著近期的微信商城等頁(yè)面的興起,相信程序員和互聯(lián)網(wǎng)的從業(yè)者都知道了js正在勢(shì)頭上了。

那么,如果你想要在前端這條路上走得更遠(yuǎn),設(shè)計(jì)模式就必須要懂。下面介紹幾種常見(jiàn)的設(shè)計(jì)模式。

一、單例模式

單例模式也稱作為單子模式,更多的也叫做單體模式。為軟件設(shè)計(jì)中較為簡(jiǎn)單但是最為常用的一種設(shè)計(jì)模式。 在JavaScript里,實(shí)現(xiàn)單例的方式有很多種,其中最簡(jiǎn)單的一個(gè)方式是使用對(duì)象字面量的方法,其字面量里可以包含大量的屬性和方法:

var mySingleton = {
property1: "something",
property2: "something else",
method1: function () {
  console.log('hello world');
}};

如果以后要擴(kuò)展該對(duì)象,你可以添加自己的私有成員和方法,然后使用閉包在其內(nèi)部封裝這些變量和函數(shù)聲明。只暴露你想暴露的public成員和方法,樣例代碼如下:

 var mySingleton = function () {
  /* 這里聲明私有變量和方法 */
  var privateVariable = 'something private';
  function showPrivate() {
    console.log(privateVariable);
  }
  /* 公有變量和方法(可以訪問(wèn)私有變量和方法) */
  return {
    publicMethod: function () {
      showPrivate();
    },
    publicVar: 'the public can see this!'
  };
};
var single = mySingleton();
single.publicMethod(); // 輸出 'something private'
console.log(single.publicVar); // 輸出 'the public can see this!'

上面的代碼很不錯(cuò)了,但如果我們想做到只有在使用的時(shí)候才初始化,那該如何做呢?為了節(jié)約資源的目的,我們可以另外一個(gè)構(gòu)造函數(shù)里來(lái)初始化這些代碼,如下:

var Singleton = (function () {
  var instantiated;
  function init() {
    /*這里定義單例代碼*/
    return {
      publicMethod: function () {
        console.log('hello world');
      },
      publicProperty: 'test'
    };
  }
  return {
    getInstance: function () {
      if (!instantiated) {
        instantiated = init();
      }
      return instantiated;
    }
  };
})();
/*調(diào)用公有的方法來(lái)獲取實(shí)例:*/
Singleton.getInstance().publicMethod();

二、工廠模式

工廠模式是由一個(gè)方法來(lái)決定到底要?jiǎng)?chuàng)建哪個(gè)類的實(shí)例, 而這些實(shí)例經(jīng)常都擁有相同的接口. 這種模式主要用在所實(shí)例化的類型在編譯期并不能確定, 而是在執(zhí)行期決定的情況。 說(shuō)的通俗點(diǎn),就像公司茶水間的飲料機(jī),要咖啡還是牛奶取決于你按哪個(gè)按鈕。

實(shí)例:

function A( name ){
       this.name = name;
    }
    function ObjectFactory(){
       var obj = {},
           Constructor = Array.prototype.shift.call( arguments );
obj.__proto__ = typeof Constructor .prototype === 'number' ? Object.prototype
: Constructor .prototype;
       var ret = Constructor.apply( obj, arguments );
       return typeof ret === 'object' ? ret : obj;
    }
    var a = ObjectFactory( A, 'svenzeng' );
    alert ( a.name ); //svenzeng

這段代碼來(lái)自es5的new和構(gòu)造器的相關(guān)說(shuō)明, 可以看到,所謂的new, 本身只是一個(gè)對(duì)象的復(fù)制和改寫過(guò)程, 而具體會(huì)生成什么是由調(diào)用ObjectFactory時(shí)傳進(jìn)去的參數(shù)所決定的。

三、 適配模式

簡(jiǎn)單的說(shuō),適配模式主要是為了解決一些接口不兼容產(chǎn)生的解決方法。借助于適配器我們可以在不修改這些不兼容接口的情況下給使用者提供統(tǒng)一的包裝過(guò)的適配接口。表面上又感覺(jué)和之前的門面模式比較像,均是對(duì)其他對(duì)象或者接口進(jìn)行包裝再呈現(xiàn),而適配器模式偏向的是解決兼容性問(wèn)題,門面模式則偏向方便性為原則。

比如一個(gè)簡(jiǎn)單的學(xué)生查詢學(xué)科成績(jī)的方法:

  function selectScore( name, id, course_id ){
  // arguments 姓名 學(xué)號(hào) 課程id
  ...
}

當(dāng)我需要一個(gè)班級(jí)某門學(xué)科的整體成績(jī)列表,而我手上只有每個(gè)學(xué)生如下的數(shù)據(jù)

[
  { name: 'lily', studentID: '0911' },
  { name: 'suny', studentID: '0912' },
  ...
]

我需要查詢 英語(yǔ) 其課程ID為 101,那么對(duì)于該任務(wù),寫一個(gè)適配器方式是很恰當(dāng)不過(guò)的

function selectEnglishScore( stutentObj ){
  selectScore( stutentObj.name, stutentObj.studentID , 101);
}

這是一個(gè)最簡(jiǎn)單的關(guān)于適配器來(lái)處理參數(shù)方面兼容的形式。 其實(shí)簡(jiǎn)單的來(lái)說(shuō),適配器模式意義上很簡(jiǎn)單 - 適配,解決兼容問(wèn)題。

例子二,比如你覺(jué)得jquery里邊的$選擇器需要改成$id才能和你的項(xiàng)目搭配,那么這時(shí)候?qū)懸粋€(gè)方法,將$轉(zhuǎn)換成$id就很輕松了。如下:

$id = function( id ){
 return jQuery( '#' + id )[0];
}

四、外觀模式

外觀模式(門面模式),是一種相對(duì)簡(jiǎn)單而又無(wú)處不在的模式。外觀模式提供一個(gè)高層接口,這個(gè)接口使得客戶端或子系統(tǒng)更加方便調(diào)用。 用一段再簡(jiǎn)單不過(guò)的代碼來(lái)表示:

var getName = function(){
 return ''svenzeng"
}
var getSex = function(){
  return 'man'
}

如果你需要分別調(diào)用getName和getSex函數(shù). 那可以用一個(gè)更高層的接口getUserInfo來(lái)調(diào)用.:

var getUserInfo = function(){
 var info = a() + b();
 return info;
}

也許你會(huì)問(wèn)為什么一開(kāi)始不把getName和getSex的代碼寫到一起, 比如這樣:

var getNameAndSex = function(){
 return 'svenzeng" + "man";
}

答案是顯而易見(jiàn)的,飯?zhí)玫某床藥煾挡粫?huì)因?yàn)槟泐A(yù)定了一份燒鴨和一份白菜就把這兩樣菜炒在一個(gè)鍋里。他更愿意給你提供一個(gè)燒鴨飯?zhí)撞?。同樣在程序設(shè)計(jì)中,我們需要保證函數(shù)或者對(duì)象盡可能的處在一個(gè)合理粒度,畢竟不是每個(gè)人喜歡吃燒鴨的同時(shí)又剛好喜歡吃白菜。 外觀模式還有一個(gè)好處是可以對(duì)用戶隱藏真正的實(shí)現(xiàn)細(xì)節(jié),用戶只關(guān)心最高層的接口。比如在燒鴨飯?zhí)撞偷墓适轮?,你并不關(guān)心師傅是先做燒鴨還是先炒白菜,你也不關(guān)心那只鴨子是在哪里成長(zhǎng)的。

最后寫個(gè)我們都用過(guò)的外觀模式例子:

var stopEvent = function( e ){  //同時(shí)阻止事件默認(rèn)行為和冒泡
 e.stopPropagation();
 e.preventDefault();
}

好了,今天的額設(shè)計(jì)模式就先到這里。如果大家想要了解更多的設(shè)計(jì)模式可以去湯姆大叔的博客欣賞哦。還有,這里的很多的設(shè)計(jì)模式其實(shí)都是將解決問(wèn)題的方法細(xì)化了的說(shuō)法,如果去看一下prototype或者jquery都會(huì)知道,其實(shí)里邊的代碼很多都用到了設(shè)計(jì)模式的。

以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,同時(shí)也希望多多支持億速云!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI