1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        如何真正理解好一個(gè)「設(shè)計(jì)模式」?

        共 3616字,需瀏覽 8分鐘

         ·

        2020-08-21 14:34


        我的施工之路

        1我的施工計(jì)劃

        2數(shù)字專題

        3字符串專題

        4列表專題

        5流程控制專題

        6編程風(fēng)格專題

        7函數(shù)使用

        8面向?qū)ο缶幊?上篇)

        9面向?qū)ο缶幊?下篇)

        10十大數(shù)據(jù)結(jié)構(gòu)

        11包和模塊使用總結(jié)

        12Python 正則使用專題總結(jié)

        真正理解設(shè)計(jì)模式

        設(shè)計(jì)模式是無(wú)數(shù)開(kāi)發(fā)者前輩,經(jīng)過(guò)大量編碼實(shí)踐,總結(jié)下來(lái)的一套能提高程序擴(kuò)展性、可復(fù)用性的哲學(xué)。它就像建筑大師多年經(jīng)驗(yàn)沉淀下來(lái)的樓宇設(shè)計(jì)方法,又像武俠小說(shuō)中的武林高手擊敗對(duì)手的武林秘籍。

        1 設(shè)計(jì)模式的由來(lái)

        實(shí)話講,很多開(kāi)發(fā)者初次接觸設(shè)計(jì)模式時(shí),覺(jué)得它太玄學(xué),明明封裝為一個(gè)對(duì)象就能解決問(wèn)題,為啥非要?jiǎng)?chuàng)建多個(gè)對(duì)象,各個(gè)對(duì)象還有引用關(guān)系,既不簡(jiǎn)約,也不可讀。學(xué)完幾個(gè)設(shè)計(jì)模式,最后真心覺(jué)得設(shè)計(jì)模式?jīng)]用!

        直到接手一個(gè)大項(xiàng)目時(shí),對(duì)設(shè)計(jì)模式的認(rèn)識(shí)才漸漸有所改變??蛻舻男枨罂倳?huì)變,幾天一個(gè)樣。于是,開(kāi)發(fā)者總要去改動(dòng)原來(lái)的類或方法。好不容易上線,客戶需求還在變,于是開(kāi)發(fā)者再回去修改原來(lái)的方法??蛻粜滦枨蟠_實(shí)實(shí)現(xiàn)了,但不要求改動(dòng)的某些功能卻意外出現(xiàn)bug,這令開(kāi)發(fā)者非常撓頭。

        于是,這些前輩們,痛定思定,要設(shè)計(jì)出一套開(kāi)發(fā)模式,既能保證住原功能的穩(wěn)定性,同時(shí)也能實(shí)現(xiàn)客戶需求變化。

        這才有了設(shè)計(jì)模式。

        2 面向特定場(chǎng)景

        前輩們發(fā)現(xiàn),為了同時(shí)實(shí)現(xiàn)原功能和新功能,一種設(shè)計(jì)模式很難做到。不同的需求場(chǎng)景,對(duì)應(yīng)開(kāi)發(fā)出不同的設(shè)計(jì)模式,久而久之,沉淀下十幾種經(jīng)典常用的設(shè)計(jì)模式。

        這些設(shè)計(jì)模式大概可分類為:創(chuàng)建對(duì)象的設(shè)計(jì)方法,定義行為的設(shè)計(jì)方法。至于創(chuàng)建對(duì)象的設(shè)計(jì)模式,前輩們根據(jù)具體的場(chǎng)景不同,又制定出幾種方法;定義行為的方法,也根據(jù)場(chǎng)景不同定義出不同的設(shè)計(jì)方法。

        3 對(duì)象工廠

        這是一種創(chuàng)建對(duì)象的設(shè)計(jì)模式。誕生它的初衷之一,是因?yàn)樵O(shè)計(jì)出了多個(gè)子類,導(dǎo)致這些類的使用者調(diào)用起來(lái)不是很便捷,于是他們對(duì)開(kāi)發(fā)這些類的作者提出需求,需要增加一個(gè)對(duì)象工廠類來(lái)管理子類,由對(duì)象工廠組裝出不同的子類對(duì)象。

        這樣,使用者只需找到對(duì)象工廠類,調(diào)用它創(chuàng)建出工廠里的任意一個(gè)對(duì)象。

        大家注意:設(shè)計(jì)模式與具體的實(shí)現(xiàn)語(yǔ)言無(wú)關(guān),它是一種提高面向?qū)ο罂蓮?fù)用性、可擴(kuò)展性的設(shè)計(jì)思想。一般來(lái)講,設(shè)計(jì)模式普遍使用的語(yǔ)言包括:Java、C#、Python等

        此處是講設(shè)計(jì)模式,簡(jiǎn)化語(yǔ)言實(shí)現(xiàn),重點(diǎn)幫助大家理解設(shè)計(jì)模式,因此不要糾結(jié)語(yǔ)法,你可以理解為下面是偽代碼

        首先定義一個(gè)接口:

        class?Interface(object):
        ??def?createCar():
        ????pass

        如下定義 3 個(gè)實(shí)現(xiàn)接口的類:

        class?A(Interface):
        ??def?createCar():
        ????print('A-method')

        class?B(Interface):
        ??def?createCar():
        ????print('B-method')
        ??
        class?C(Interface):
        ??def?createCar():
        ????print('C-method')

        創(chuàng)建一個(gè)對(duì)象工廠,專門(mén)用于創(chuàng)建A或B或C:

        class?CarFactory(object):
        ??def?getObject(methodStr):
        ????if?methodStr?==?'A':
        ??????return?A()?#?返回A對(duì)象
        ????if?methodStr?==?'B':
        ??????return?B()
        ????if?methodStr?==?'C':
        ??????return?C()

        使用時(shí),通過(guò) CarFactory().getObject('C') 得到C對(duì)象,調(diào)用C對(duì)象的方法createCar就能根據(jù)此方法造車。

        4 思考一下

        學(xué)習(xí)設(shè)計(jì)模式的最終目標(biāo)是要用到實(shí)際開(kāi)發(fā)中,要靈活運(yùn)用,要養(yǎng)成一種使用直覺(jué)。上版對(duì)象工廠實(shí)現(xiàn),大家對(duì)其有何預(yù)期?

        首先來(lái)看,如果將來(lái)生成Car又增加一種D方法,于是乎,需要增加下面的代碼:

        新增一個(gè)類D,這是沒(méi)有問(wèn)題的,符合面向?qū)ο蟮目蓴U(kuò)展性:

        class?D(Interface):
        ??def?createCar():
        ????print('D-method')

        但是對(duì)象工廠CarFactory這個(gè)模塊就要修改內(nèi)部的方法getObject,增加一條生成D對(duì)象的分支。但這確實(shí)破壞了類的封裝!

        為解決此問(wèn)題,實(shí)際上還可以進(jìn)一步抽象,進(jìn)一步擴(kuò)展出幾個(gè)類。比如增加一個(gè)抽象工廠類:

        class?CarFactoryInterface(object):
        ??pass

        重新創(chuàng)建一個(gè)實(shí)現(xiàn)接口的工廠類:CarFactoryExtend,從而不用修改用來(lái)的類文件。

        class?CarFactoryExtend(CarFactoryInterface):
        ????def?getObject(methodStr):
        ????if?methodStr?==?'A':
        ??????return?A()?#?返回A對(duì)象
        ????if?methodStr?==?'B':
        ??????return?B()
        ????if?methodStr?==?'C':
        ??????return?C()
        ????if?methodStr?==?'D':
        ???????return?D()

        以上設(shè)計(jì)模式就是所謂的抽象工廠模式。你看,這些設(shè)計(jì)模式的形成都是由需求背景的。因此,不是先有設(shè)計(jì)模式后,開(kāi)發(fā)者們循著設(shè)計(jì)模式去解決實(shí)際需求;而恰恰相反,是有了源源不斷的開(kāi)發(fā)需求后,日積月累沉淀下這十幾種實(shí)際模式。并被后來(lái)的開(kāi)發(fā)者們爭(zhēng)相模仿學(xué)習(xí),更是被領(lǐng)悟其思想精髓者,大呼其好用。

        5 設(shè)計(jì)禁忌

        設(shè)計(jì)模式的幾個(gè)禁忌,大概總結(jié)為以下幾點(diǎn):

        • 不是越抽象越好,也不是不抽象,而是要把握好一個(gè)度;
        • 繼承鏈條的根不要是具體的實(shí)現(xiàn)類,因?yàn)榫唧w不等于抽象,根最好是接口或抽象類;
        • 不要生搬硬套各種設(shè)計(jì)模式,雖然每個(gè)模式都有一個(gè)標(biāo)準(zhǔn)版本,但日常使用一般不是死板的模仿,一個(gè)角色都不能少;
        • 設(shè)計(jì)模式不是無(wú)用的,如果喜歡總結(jié),再工作幾年后,腦子里會(huì)有幾個(gè)常用設(shè)計(jì)模式;
        • 沒(méi)有一個(gè)通用的設(shè)計(jì)模式,一個(gè)設(shè)計(jì)模式往往只針對(duì)某個(gè)特定場(chǎng)景。

        6 練習(xí)一個(gè)設(shè)計(jì)模式

        有一種設(shè)計(jì)模式常被用于算法開(kāi)發(fā),先不說(shuō)它的名字,我們根據(jù)實(shí)際的需求場(chǎng)景,倒推出這個(gè)設(shè)計(jì)模式。

        解決某個(gè)特定問(wèn)題可以使用策略A類里的方法solve:

        class?A(object):
        ??def?solver():
        ????print('A?method')

        后來(lái)又發(fā)明方法B類:

        class?B(object):
        ??def?solver():
        ????print('B?method')

        設(shè)計(jì)模式最重要一條:繼承鏈條的根要是抽象類或接口,因此提取出接口StrategyInterface:

        class?StrategyInterface(object):
        ????def?solver():?#?這是接口的方法
        ??????pass

        所以,A類和B類稍作修改:

        class?A(StrategyInterface):
        ??def?solver():
        ????print('A?method')

        class?B(StrategyInterface):
        ??def?solver():
        ????print('B?method')

        使用方在使用這些策略時(shí),到底該使用哪個(gè)策略呢?為了方便策略管理,又多出一個(gè)策略管理類:

        class?StrategyContext(object)
        ??def?setStrategy(StrategyInterface):

        ????self.strategy?=?StrategyInterface
        ??def?callMethod():
        ????print('context?of?strategy')
        ????self.strategy.solver()
        ????print('done')#?other?things????

        實(shí)際使用時(shí)的方法:

        context?=?StrategyContext()
        context.setStrategy(A())?
        context.callMethod()

        以上就是策略模式,是一種關(guān)于行為控制的設(shè)計(jì)模式。

        如果不想要StrategyContext類,實(shí)際使用時(shí)的方法如下:

        StrategyInterface?strategy?=?A()
        print('before?strategy')
        strategy.solver()
        print('done')#?other?things????

        這樣又未嘗不可呢,繼承鏈?zhǔn)諗坑诮涌?,只不過(guò)使用者需要多寫(xiě)一些可能不是"太標(biāo)準(zhǔn)"的代碼。依賴于設(shè)計(jì)模式,又能獨(dú)立思考某些設(shè)計(jì)模式,這樣更有可能靈活使用設(shè)計(jì)模式。

        Python與算法社區(qū)

        一個(gè)寫(xiě)了400+篇原創(chuàng)的技術(shù)號(hào)

        瀏覽 62
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            91精品人妻一区二区三区蜜桃 | 97人妻无码 | 91精品人妻一区二区三区四区 | 一本一道AV无码 | 黄色老鸭窝视频 | 欧美肏屄 | 乱色AV | 日日弄 | 我要看免费的毛片 | 妈妈假装睡着不盖被子 |