成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

學(xué)習(xí)這些設(shè)計(jì)模式,讓你寫(xiě)出更優(yōu)雅的代碼

用戶(hù)84 / 1228人閱讀

摘要:寫(xiě)代碼容易,寫(xiě)出優(yōu)雅的代碼難,寫(xiě)易于維護(hù)的容易擴(kuò)展的結(jié)構(gòu)清晰的代碼應(yīng)該是每位開(kāi)發(fā)者努力的目標(biāo),而學(xué)習(xí)設(shè)計(jì)模式,合理的的使用能讓我們離這個(gè)目標(biāo)更進(jìn)一步。

寫(xiě)代碼容易,寫(xiě)出優(yōu)雅的代碼難,寫(xiě)易于維護(hù)的、容易擴(kuò)展的、結(jié)構(gòu)清晰的代碼應(yīng)該是每位開(kāi)發(fā)者努力的目標(biāo),而學(xué)習(xí)設(shè)計(jì)模式,合理的的使用能讓我們離這個(gè)目標(biāo)更進(jìn)一步。最近看了《Javascript設(shè)計(jì)模式與開(kāi)發(fā)實(shí)踐》這本書(shū),一言以蔽之,真不錯(cuò)的一本書(shū),在這里總結(jié)一下書(shū)中介紹的主要的在JavaScript中我們可以用到的一些設(shè)計(jì)模式。設(shè)計(jì)模式的思想是值得反復(fù)咀嚼、思考的,在以后的業(yè)務(wù)實(shí)現(xiàn)中,應(yīng)該結(jié)合這些思想,加以合理的使用

更多內(nèi)容

單例模式
單例模式保證類(lèi)只有一個(gè)實(shí)例,并提供一個(gè)訪(fǎng)問(wèn)它的全局訪(fǎng)問(wèn)點(diǎn)

js中實(shí)現(xiàn)

  function getSingle(fn){
    let result

    return function (){
        return result || (result=fn.apply(this,arguments))
    }

  }
策略模式
解決一個(gè)問(wèn)題的多個(gè)方法,將每種方法獨(dú)立封裝起來(lái),相互可以替換

一個(gè)基于策略模式的程序至少由兩部分組成,一個(gè)是一組策略類(lèi),策略類(lèi)封裝了具體的算法,并負(fù)責(zé)具體的計(jì)算過(guò)程,一個(gè)是環(huán)境類(lèi),環(huán)境類(lèi)接受客戶(hù)的請(qǐng)求,隨后把請(qǐng)求委托給某個(gè)策略類(lèi)

策略模式的一個(gè)使用場(chǎng)景:表單驗(yàn)證,將不同驗(yàn)證規(guī)則封裝成一組策略,避免了多重條件判斷語(yǔ)句

一句經(jīng)典的話(huà):在函數(shù)作為一等對(duì)象的語(yǔ)言中,策略模式是隱性的,策略就是值為函數(shù)的變量

例子:

    const S = (salary)=>{
        return salary * 4
    }
    const A = (salary)=>{
        return salary * 3
    }
    const B = (salary)=>{
        return salary * 2
    }

    const calculate = (fun,salary)=>{
        return fun(salary)
    }
    calculate(S,1000)
代理模式
代理模式為一個(gè)對(duì)象提供一個(gè)代用品或占位符,以便控制對(duì)它的訪(fǎng)問(wèn)

不直接和本體進(jìn)行交互,而是在中間加入一層代理,代理來(lái)處理一些不需要本體做的操作

var myImage=function(){
    var imgNode=document.createElement("img")
    document.body.appendChild(imgNode)
    return {
        setImg(src){
            imgNode.src=src
        }
    }
}

var proxyImg=function(){
    var img =new Image()
    img.onload=function(){
        myImage.setSrc(this.src)
    }
    return {
        setImg(src){
            myImage.setSrc(‘loading.png’)
            img.src=src      
        }
    }
}

代理的意義

對(duì)單一職責(zé)原則的一種表現(xiàn),單一職責(zé)原則指的是,一個(gè)函數(shù)或類(lèi)應(yīng)該只負(fù)責(zé)一件事,如何一個(gè)函數(shù)職責(zé)太多,等于把這些職責(zé)耦合在了一起,當(dāng)一部分需要改動(dòng)時(shí),很有可能就影響到了函數(shù)的其他部分

觀察者和發(fā)布訂閱模式

觀察者和發(fā)布、訂閱模式使程序的兩部分不必緊密耦合在一起,而是通過(guò)通知的方式來(lái)通信

觀察者模式

一個(gè)對(duì)象維持一系列依賴(lài)于它的對(duì)象,當(dāng)對(duì)象狀態(tài)發(fā)生改變時(shí)主動(dòng)通知這些依賴(lài)對(duì)象

這里注意是對(duì)象直接管理著依賴(lài)列表,這點(diǎn)也是觀察者模式和發(fā)布、訂閱模式的主要區(qū)別

class Subject{
        constructor(){
            this.observers=[]
        }
        add(observer){
            this.observers.push(observer)
        }
        notify(data){
            for(let observer of this.observers){
                observer.update(data)
            }
        }
    }

    class Observer{
        update(){

        }
    }

觀察者模式的缺點(diǎn)是對(duì)象必須自己維護(hù)一個(gè)觀察者列表,當(dāng)對(duì)象狀態(tài)有更新時(shí),直接調(diào)用其他對(duì)象的方法,所以,在使用中,我們一般采用一種變形方式,即發(fā)布訂閱模式

發(fā)布訂閱模式

該模式在主題和觀察者之間加入一層管道,使得主題和觀察者不直接交互,發(fā)布者將內(nèi)容發(fā)布到管道,訂閱者訂閱管道里的內(nèi)容,目的是避免訂閱者和發(fā)布者之間產(chǎn)生依賴(lài)關(guān)系

    class Pubsub{

        constuctor(){
            this.pubsub={}
            this.subId=-1
        }

        publish(topic,data){
            if(!this.pubsub[topic]) return
            const subs=this.pubsub[topic]
            const len=subs.length
            while(len--){
                subs[len].update(topic,data)
            }
        }

        /**
        *  topic {string}
        *  update {function}
        */
        subscribe(topic,update){
            !this.pubsub[topic] && (this.pubsub[topic]=[])
            this.subId++
            this.pubsub[topic].push({
                token:this.subId,
                update
            })
        }

        unsubscribe(token){
            for(let topic in this.pubsub){
                if(this.pubsub.hasOwnProperty(topic)){
                    const current=this.pubsub[topic]
                    for(let i=0,j=current.length;i

發(fā)布訂閱模式是在框架設(shè)計(jì)中經(jīng)常使用的一種設(shè)計(jì)模式,angularjs中的自定義事件,Rxjs,狀態(tài)管理的redux等都能看到它的身影

命令模式
命令模式的命令指的是一個(gè)執(zhí)行某些特定事情的指令

命令模式最常見(jiàn)的使用場(chǎng)景是:有時(shí)候需要向某些對(duì)象發(fā)送請(qǐng)求,但是不知道請(qǐng)求的接受者是誰(shuí),也不知道被請(qǐng)求的操作是什么。此時(shí)希望用一種松耦合的方式來(lái)設(shè)計(jì)程序,是使得請(qǐng)求發(fā)送者和接受者消除彼此之間的耦合關(guān)系

命令模式的由來(lái),其實(shí)是回調(diào)函數(shù)的一個(gè)面向?qū)ο蟮奶娲?/strong>

一句話(huà)來(lái)說(shuō),命令模式就是用一個(gè)函數(shù)來(lái)包裹一個(gè)具體的實(shí)現(xiàn),這個(gè)函數(shù)統(tǒng)一定義了一個(gè)execute方法來(lái)調(diào)用具體的實(shí)現(xiàn)方法,而請(qǐng)求者只要和這個(gè)命令函數(shù)交流就行

享元模式
享元模式顧名思義,共享一些單元,用于優(yōu)化重復(fù)、緩慢及數(shù)據(jù)共享效率較低的代碼

應(yīng)用:一是用于數(shù)據(jù)層,處理內(nèi)存中保存的大量相似對(duì)象的共享數(shù)據(jù),二是用于DOM層,事件代理

在享元模式中,有個(gè)有關(guān)兩個(gè)狀態(tài)的概念-內(nèi)部和外部

內(nèi)部狀態(tài)存儲(chǔ)于對(duì)象內(nèi)部,可以被一些對(duì)象共享,獨(dú)立于具體的場(chǎng)景,通常不會(huì)變

外部狀態(tài)根據(jù)場(chǎng)景而變化

剝離了外部狀態(tài)的對(duì)象成為共享對(duì)象,外部狀態(tài)在必要時(shí)被傳入共享對(duì)象來(lái)組成一個(gè)完整的對(duì)象

使用享元模式的幾個(gè)步驟:

以書(shū)中文件上傳的例子描述

剝離外部狀態(tài)

 class Upload{

    constructor(type){
        this.uploadType=type
    }

    delFile(id){
        uploadManager.setExternalState(id,this) //這里就是組裝外部狀態(tài)來(lái)使共享對(duì)象變成一個(gè)具體的對(duì)象
        if(this.fileSize<3000){
            //直接刪除
            return
        }
        //彈窗詢(xún)問(wèn)確認(rèn)刪除?
    }

 }

使用工廠(chǎng)進(jìn)行對(duì)象實(shí)例化

    var UploadFactory=(function(){
        const flyWeightObjs={}
        return {
            create(uploadType){
                if(flyWeightObjs[uploadType]){
                    return flyWeightObjs[uploadType]
                }
                return flyWeightObjs[uploadType]=new Upload(uoloadType)
            }
        }
    })()

使用管理器封裝外部狀態(tài)

var uploadManager=(function(){
    var uploadDatabase={}
    return {
        add(id,uploadType,fileSize,fileName){
            var flyWeightObj=UploadFactory.create(uploadType) //那個(gè)被共享的對(duì)象
            //創(chuàng)建結(jié)點(diǎn)...
            //刪除操作
            dom.onclick=function(){
                flyWeightObj.delFile(id) //這個(gè)共享在步驟1中會(huì)被組合,可以看到,只有在刪除操作的時(shí)候,我們才需要那些外部狀態(tài)
            }
            uploadDatabase[id]={
                fileName,
                fileSize,
                dom
            }
            return flyWeightObj
        },
        setExternalState(id,flyWeight){
            var externalState=uploadDatabase[id]
            Object.assign(flyWeight,externalState)
        }
    }
})()
責(zé)任鏈模式
將一個(gè)請(qǐng)求以此傳遞給多個(gè)函數(shù),若請(qǐng)求符合當(dāng)前函數(shù)要求,則當(dāng)前函數(shù)處理,否則,傳給下一個(gè)

很好很強(qiáng)大

責(zé)任鏈模式可以很好的避免大量的if,else if,else

if (Function.prototype.chainAfter) {
    throw new Error("the chainAfter method already exist")
} else {
    Function.prototype.chainAfter = function (fn) {
        return (...args) => {
            const ret = this.apply(this, [...args, () => {
                return fn && fn.apply(this, args)
            }])
            if (ret === "NEXT") {
                return fn && fn.apply(this, args)
            }
            return ret
        }
    }
}

/**
 * example
 * class Test{
 *  
 *     test(...args){
 *            alert("test")
 *            return "NEXT"
 *     }
 * 
 *     test1(...args){
 * 
 *            setTimeout(()=>{
 *                  alert("test1")
 *                  args.pop()()
 *            })   
 *     }
 * 
 *     test2(...args){
 *            alert("test2")
 *     }
 * 
 *      $onInit(){
 *          const chain = this.test.bind(this)
 *                .chainAfter(this.test1.bind(this))
 *                .chainAfter(this.test2.bind(this))
 *         chain(1,2,3)
 *      }
 * }
 * 
 */
裝飾者模式
在不改變?cè)泻瘮?shù)或?qū)ο蠊δ艿幕A(chǔ)上,給它們新加功能

用AOP裝飾函數(shù)

if (Function.prototype.before) {
    throw new Error("the before method already exist")
} else {
    Function.prototype.before = function (beforefn) {
        return () => {
            if (beforefn.apply(this, arguments)) {
                this.apply(this, arguments)
            }
        }
    }
}

if (Function.prototype.after) {
    throw new Error("the after method already exist")
} else {
    Function.prototype.after = function (afterfn) {
        return () => {
            this.apply(this, arguments)
            afterfn.apply(this, arguments)
        }
    }
}
狀態(tài)模式
允許一個(gè)對(duì)象在其內(nèi)部狀態(tài)改變時(shí)改變它的行為,對(duì)象看起來(lái)似乎修改了它的類(lèi)

要點(diǎn):將狀態(tài)封裝成獨(dú)立的函數(shù),并將請(qǐng)求委托給當(dāng)前的狀態(tài)對(duì)象,當(dāng)對(duì)象的內(nèi)部狀態(tài)改變時(shí),會(huì)帶來(lái)不同的行為變化

電燈的例子:

一個(gè)按鈕控制電燈的開(kāi)關(guān),按一下是開(kāi),再按一下是關(guān)

初始實(shí)現(xiàn):

class Light{
    constructor(){
        this.state="off",
        this.button=null
    }
    init(){
        //創(chuàng)建按鈕結(jié)點(diǎn)
        .....

        this.button.onClick=()=>{
            this.btnPressed()
        }
    }
    btnPressed(){
        if(this.state=="off"){
            this.state="on
        }else {
            this.state="off"
        }
    }
}

這段代碼的缺點(diǎn)就是不易擴(kuò)展,當(dāng)要加入一種閃動(dòng)的狀態(tài)時(shí),就要修改btnPressed中的代碼

使用狀態(tài)模式改寫(xiě)

class Light{
    constructor(){
        this.state=FSM.off,
        this.button=null
    }
    init(){
        //創(chuàng)建按鈕結(jié)點(diǎn)
        .....

        this.button.onClick=()=>{
            this.state.btnPressed.call(this)
        }
    }
}

const FSM={
    on:{
        btnPressed(){
            //處理
            this.state=FMS.on
        }
    },
    off:{
        btnPressed(){
            //處理
            this.state=FMS.off
        }
    }
}

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/51533.html

相關(guān)文章

  • 學(xué)習(xí)這些設(shè)計(jì)模式,讓你寫(xiě)出優(yōu)雅代碼

    摘要:寫(xiě)代碼容易,寫(xiě)出優(yōu)雅的代碼難,寫(xiě)易于維護(hù)的容易擴(kuò)展的結(jié)構(gòu)清晰的代碼應(yīng)該是每位開(kāi)發(fā)者努力的目標(biāo),而學(xué)習(xí)設(shè)計(jì)模式,合理的的使用能讓我們離這個(gè)目標(biāo)更進(jìn)一步。 寫(xiě)代碼容易,寫(xiě)出優(yōu)雅的代碼難,寫(xiě)易于維護(hù)的、容易擴(kuò)展的、結(jié)構(gòu)清晰的代碼應(yīng)該是每位開(kāi)發(fā)者努力的目標(biāo),而學(xué)習(xí)設(shè)計(jì)模式,合理的的使用能讓我們離這個(gè)目標(biāo)更進(jìn)一步。最近看了《Javascript設(shè)計(jì)模式與開(kāi)發(fā)實(shí)踐》這本書(shū),一言以蔽之,真不錯(cuò)的一本...

    songjz 評(píng)論0 收藏0
  • 這些JavaScript編程黑科技,裝逼指南,高逼格代碼,讓你驚嘆不已

    摘要:但是,構(gòu)造函數(shù)注意是大寫(xiě)的有點(diǎn)特別。構(gòu)造函數(shù)接受的參數(shù)中,第一個(gè)是要傳入的參數(shù)名,第二個(gè)是函數(shù)內(nèi)的代碼用字符串來(lái)表示。 Javascript是一門(mén)很吊的語(yǔ)言,我可能學(xué)了假的JavaScript,哈哈,大家還有什么推薦的,補(bǔ)充送那啥邀請(qǐng)碼。 本文秉承著:你看不懂是你SB,我寫(xiě)的代碼就要牛逼。 1、單行寫(xiě)一個(gè)評(píng)級(jí)組件 ★★★★★☆☆☆☆☆.slice(5 - rate, 10 - rate...

    曹金海 評(píng)論0 收藏0
  • 這些JavaScript編程黑科技,裝逼指南,高逼格代碼,讓你驚嘆不已

    摘要:但是,構(gòu)造函數(shù)注意是大寫(xiě)的有點(diǎn)特別。構(gòu)造函數(shù)接受的參數(shù)中,第一個(gè)是要傳入的參數(shù)名,第二個(gè)是函數(shù)內(nèi)的代碼用字符串來(lái)表示。 Javascript是一門(mén)很吊的語(yǔ)言,我可能學(xué)了假的JavaScript,哈哈,大家還有什么推薦的,補(bǔ)充送那啥邀請(qǐng)碼。 本文秉承著:你看不懂是你SB,我寫(xiě)的代碼就要牛逼。 1、單行寫(xiě)一個(gè)評(píng)級(jí)組件 ★★★★★☆☆☆☆☆.slice(5 - rate, 10 - rate...

    MorePainMoreGain 評(píng)論0 收藏0
  • 這些JavaScript編程黑科技,裝逼指南,高逼格代碼,讓你驚嘆不已

    摘要:但是,構(gòu)造函數(shù)注意是大寫(xiě)的有點(diǎn)特別。構(gòu)造函數(shù)接受的參數(shù)中,第一個(gè)是要傳入的參數(shù)名,第二個(gè)是函數(shù)內(nèi)的代碼用字符串來(lái)表示。 Javascript是一門(mén)很吊的語(yǔ)言,我可能學(xué)了假的JavaScript,哈哈,大家還有什么推薦的,補(bǔ)充送那啥邀請(qǐng)碼。 本文秉承著:你看不懂是你SB,我寫(xiě)的代碼就要牛逼。 1、單行寫(xiě)一個(gè)評(píng)級(jí)組件 ★★★★★☆☆☆☆☆.slice(5 - rate, 10 - rate...

    isLishude 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<