JavaScript設(shè)計模式

你將在本文中,了解什么是設(shè)計模式!

你將了解設(shè)計模式有什么優(yōu)點!

你將了解兩種設(shè)計模式-觀察者模式和裝飾模式!

一、什么是設(shè)計模式

  什么是設(shè)計模式咸产?其實簡單可以理解為,設(shè)計模式其實是一套理論仲闽,它可以提高代碼的可重用性脑溢,增強系統(tǒng)的可維護性,以及解決一系列的復(fù)雜問題赖欣。模式的另一種解釋就是一個我們?nèi)绾谓鉀Q問題的模版屑彻,提供解決問題的一種方案。

二顶吮、設(shè)計模式的優(yōu)點

模式是行之有效的一種解決方法:通過長期以來前輩們提供固定的解決方案在軟件開發(fā)中出現(xiàn)的問題社牲。

模式是可以很容易地重用:一個模式通常反映解決一些問題可以開箱即用的方法。

模式善于表達:一般有一組結(jié)構(gòu)和詞匯可以非常優(yōu)雅地幫助表達相當大的解決方案悴了。

注:模式不是標準的解決方案搏恤,模式也不能解決所有的設(shè)計問題,也不能代替我們優(yōu)秀的軟件設(shè)計師湃交。模式的角色僅僅提供給我們一個解決方案熟空。

三、JavaScript設(shè)計模式

1搞莺、JavaScript設(shè)計模式之觀察者模式:

先說一下個人理解:觀察者模式又稱“發(fā)布-訂閱(Publish/Subscribe)”息罗,發(fā)布與訂閱是兩個不同對象的功能。在具體編程中才沧,發(fā)布者有了新的內(nèi)容迈喉,需要向訂閱者推送數(shù)據(jù),若訂閱者退訂了則要對發(fā)布者中的訂閱者列表進行更新温圆。

觀察者模式主要應(yīng)用于對象之間一對多的依賴關(guān)系挨摸,當一個對象發(fā)生改變時,多個對該對象有依賴的其他對象也會跟著做出相應(yīng)改變捌木,這就非常適合用觀察者模式來實現(xiàn)。使用觀察者模式可以根據(jù)需要增加或刪除對象嫉戚,解決一對多對象間的耦合關(guān)系刨裆,使程序更易于擴展和維護澈圈。

應(yīng)用場景:

【1】微信公眾號訂閱,多個讀者訂閱一個微信公眾號帆啃,一旦公眾號有更新瞬女,多個讀者都會收到更新。(郵箱訂閱同理)

【2】在《大話設(shè)計模式》一書中努潘,提到類似的情況:如果針對發(fā)布者內(nèi)容而訂閱者要做不同的事情呢诽偷?比如一個按鈕和三個矩形,點擊按鈕的時候疯坤,第一個矩形增加寬度报慕,第二個矩形增加高度,第三個矩形則變成圓角矩形又該怎么做呢压怠?當然我們可以在三個矩形的update內(nèi)部寫具體的實現(xiàn)代碼眠冈,但是這update豈不是沒有一個具體的功能描述了嗎?該書中用“事件委托”解決了這個問題(此處事件委托和DOM中的事件委托應(yīng)該是兩碼事)菌瘫,我個人理解這個“事件委托”在javascript中可以用一個數(shù)組表示蜗顽,然后里面放各個訂閱者的不同名字的update,然后一一調(diào)用雨让。

代碼解讀:

--發(fā)布者相關(guān)信息解讀//發(fā)布者

  function Publisher(){
        this.observers = [];  
        this.state = "";  
    }

  //增加

    Publisher.prototype.addOb=function(observer){
        var flag = false;
        for (var i = this.observers.length - 1; i >= 0; i--) {
            if(this.observers[i]===observer){
                flag=true;                
            }
        };
        if(!flag){
            this.observers.push(observer);
        }
        return this;
    }

   //移除

    Publisher.prototype.removeOb=function(observer){
        var observers = this.observers;
        for (var i = 0; i < observers.length; i++) {
            if(observers[i]===observer){
                observers.splice(i,1);
            }
        };
        return this;
    }

 //更新

    Publisher.prototype.notice=function(){
        var observers = this.observers;
        for (var i = 0; i < observers.length; i++) {
                observers[i].update(this.state);
        };
    }

--訂閱者相關(guān)信息解讀//訂閱者

(訂閱者功能很簡單雇盖,只需要一個更新(update)功能,但是每一個訂閱者的更新功能可能不一樣栖忠,例如應(yīng)用場景中提到的【2】)

    function Subscribe(){
        this.update = function(data){
              console.log(data);
        };
    }

--為了滿足訂閱者不同的需求崔挖,可以為每一個訂閱者的實例設(shè)置單獨的update。

//實際應(yīng)用

    var obA = new Subscribe(),
        obB = new Subscribe();

    var pba = new Publisher();

    pba.addOb(obA);
    pba.addOb(obB);

    obA.update = function(state){
        console.log(state+"hello!");
    }
    obB.update = function(state){
        console.log(state+"world!");
    }
    pba.state = "open ";
    pba.notice();

so--彩蛋

一般pm的需求肯定不會這樣提娃闲。mrd文檔一般為第一個input框輸入中文姓名拼音虚汛,第二個input框(不可寫)自動“0881+姓名拼音”,第三個文本框(不可寫)自動生成郵箱“拼音+888@163.com

部分代碼如下:


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <div>
        <label>員工姓名拼音:<input type="text" id="pba" placeholder="請輸入員工姓名拼音" /></label><br /><br />
        <label>生成編號:<input type="text" id="oba" readonly /></label>
        <label>生成郵箱:<input type="text" id="obb" readonly /></label>
    </div>

    <script type="text/javascript">
        //發(fā)布者
        function Publisher(obj){
            this.observers = [];
            var state = obj.value;     //讓該內(nèi)容不能直接訪問

            //新增兩個對于state的操作 獲取/更新
            this.getState=function(){
                return state;
            }
            this.setState=function(value){
                state = value;
                this.notice();
            }
            this.obj = obj;

        }
        Publisher.prototype.addOb=function(observer){
            var flag = false;
            for (var i = this.observers.length - 1; i >= 0; i--) {
                if(this.observers[i]===observer){
                    flag=true;                
                }
            };
            if(!flag){
                this.observers.push(observer);
            }
            return this;
        }
        Publisher.prototype.removeOb=function(observer){
            var observers = this.observers;
            for (var i = 0; i < observers.length; i++) {
                if(observers[i]===observer){
                    observers.splice(i,1);
                }
            };
            return this;
        }
        Publisher.prototype.notice=function(){
            var observers = this.observers;
            for (var i = 0; i < observers.length; i++) {
                    observers[i].update(this.getState());
            };
        }

        //訂閱者
        function Subscribe(obj){
            this.obj = obj;
            this.update = function(data){
                this.obj.value = data;
            };
        }

        //實際應(yīng)用
        var oba = new Subscribe(document.querySelector("#oba")),
            obb = new Subscribe(document.querySelector("#obb"));

        var pba = new Publisher(document.querySelector("#pba"));

        pba.addOb(oba);
        pba.addOb(obb);

        oba.update = function(state){
            this.obj.value = “0881”+state;
        }
        obb.update = function(state){
            this.obj.value = state+“888@163.com”;
        }

        pba.obj.addEventListener('keyup',function(){
            pba.setState(this.value);
        });
        
    </script>
</body>
</html>

2皇帮、JavaScript設(shè)計模式之裝飾者模式:

先說一下個人理解:裝飾者模式重點在裝飾卷哩,同樣都是女生,如果其中一個女生化個妝涂個口紅打扮(裝飾)一下即可秒變女神(奪人眼球的功能)属拾。

其實将谊,實現(xiàn)裝飾者模式的其中一個方法是使得每個裝飾者成為一個對象,并且該對象包含了應(yīng)該被重載的方法渐白。每個裝飾者實際上繼承了目前已經(jīng)被前一個裝飾者進行增強后的對象尊浓。每個裝飾方法在“繼承的對象”上調(diào)用了同樣的方法并獲取其值,此外它還繼續(xù)執(zhí)行了一些操作纯衍。

應(yīng)用場景:

【1】之前項目遇到過的栋齿,創(chuàng)建會員卡,會員卡的外觀以及會員卡詳情都是一樣的功能。但是瓦堵,對于不同的用戶會和會員卡有不一樣的聯(lián)系基协,例如:未激活,未領(lǐng)取菇用,設(shè)置默認卡等澜驮。可以針對會員卡這個對象惋鸥,給予不一樣的修飾函數(shù)杂穷。若后面要對該會員卡還有其他相應(yīng)的交互,直接裝飾即可~

【2】假設(shè)我們在編寫一個飛機大戰(zhàn)的游戲卦绣,隨著經(jīng)驗值的增加耐量,我們操作的飛機對象可以升級成更厲害的飛機,一開始這些飛機只能發(fā)射普通的子彈迎卤,升到第二級時可以發(fā)射導(dǎo)彈拴鸵,升到第三級時可以發(fā)射原子彈。

部分代碼如下:

var Plane = function(){};
    Plane.prototype.fire = function(){
        console.log( '發(fā)射普通子彈' );
    }

    var MissileDecorator = function( plane ){
        this.plane = plane;
    }
    MissileDecorator.prototype.fire = function(){
        this.plane.fire();
        console.log( '發(fā)射導(dǎo)彈' );
    }
    var AtomDecorator = function( plane ){
        this.plane = plane;
    }
    AtomDecorator.prototype.fire = function(){
        this.plane.fire();
        console.log( '發(fā)射原子彈' );
    }

    var plane = new Plane();
    plane = new MissileDecorator( plane );
    plane = new AtomDecorator( plane );
    plane.fire();// 分別輸出: 發(fā)射普通子彈蜗搔、發(fā)射導(dǎo)彈劲藐、發(fā)射原子彈

導(dǎo)彈類和原子彈類的構(gòu)造函數(shù)都接受參數(shù)plane 對象,并且保存好這個參數(shù)樟凄,在它們的fire方法中聘芜,除了執(zhí)行自身的操作之外,還調(diào)用plane 對象的fire 方法缝龄。

因為裝飾者對象和它所裝飾的對象擁有一致的接口汰现,所以它們對使用該對象的客戶來說是透明的,被裝飾的對象也并不需要了解它曾經(jīng)被裝飾過叔壤,這種透明性使得我們可以遞歸地嵌套任意多個裝飾者對象瞎饲。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市炼绘,隨后出現(xiàn)的幾起案子嗅战,更是在濱河造成了極大的恐慌,老刑警劉巖俺亮,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件驮捍,死亡現(xiàn)場離奇詭異,居然都是意外死亡脚曾,警方通過查閱死者的電腦和手機东且,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來本讥,“玉大人珊泳,你說我怎么就攤上這事鲁冯。” “怎么了色查?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵晓褪,是天一觀的道長。 經(jīng)常有香客問我综慎,道長,這世上最難降的妖魔是什么勤庐? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任示惊,我火速辦了婚禮,結(jié)果婚禮上愉镰,老公的妹妹穿的比我還像新娘米罚。我一直安慰自己,他們只是感情好丈探,可當我...
    茶點故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布录择。 她就那樣靜靜地躺著,像睡著了一般碗降。 火紅的嫁衣襯著肌膚如雪隘竭。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天讼渊,我揣著相機與錄音动看,去河邊找鬼。 笑死爪幻,一個胖子當著我的面吹牛菱皆,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播挨稿,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼仇轻,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了奶甘?” 一聲冷哼從身側(cè)響起篷店,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎甩十,沒想到半個月后船庇,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡侣监,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年鸭轮,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片橄霉。...
    茶點故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡窃爷,死狀恐怖邑蒋,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情按厘,我是刑警寧澤医吊,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站逮京,受9級特大地震影響卿堂,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜懒棉,卻給世界環(huán)境...
    茶點故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一草描、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧策严,春花似錦穗慕、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至倔韭,卻和暖如春术浪,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背寿酌。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工添吗, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人份名。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓碟联,卻偏偏與公主長得像,于是被迫代替她去往敵國和親僵腺。 傳聞我的和親對象是個殘疾皇子鲤孵,可洞房花燭夜當晚...
    茶點故事閱讀 43,452評論 2 348

推薦閱讀更多精彩內(nèi)容