<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          如何真正理解好一個(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ì)模式是無數(shù)開發(fā)者前輩,經(jīng)過大量編碼實(shí)踐,總結(jié)下來的一套能提高程序擴(kuò)展性、可復(fù)用性的哲學(xué)。它就像建筑大師多年經(jīng)驗(yàn)沉淀下來的樓宇設(shè)計(jì)方法,又像武俠小說中的武林高手擊敗對(duì)手的武林秘籍。

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

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

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

          于是,這些前輩們,痛定思定,要設(shè)計(jì)出一套開發(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)開發(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)用起來不是很便捷,于是他們對(duì)開發(fā)這些類的作者提出需求,需要增加一個(gè)對(duì)象工廠類來管理子類,由對(duì)象工廠組裝出不同的子類對(duì)象。

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

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

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

          首先定義一個(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ì)象工廠,專門用于創(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í),通過 CarFactory().getObject('C') 得到C對(duì)象,調(diào)用C對(duì)象的方法createCar就能根據(jù)此方法造車。

          4 思考一下

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

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

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

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

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

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

          class?CarFactoryInterface(object):
          ??pass

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

          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ì)模式后,開發(fā)者們循著設(shè)計(jì)模式去解決實(shí)際需求;而恰恰相反,是有了源源不斷的開發(fā)需求后,日積月累沉淀下這十幾種實(shí)際模式。并被后來的開發(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ì)模式不是無用的,如果喜歡總結(jié),再工作幾年后,腦子里會(huì)有幾個(gè)常用設(shè)計(jì)模式;
          • 沒有一個(gè)通用的設(shè)計(jì)模式,一個(gè)設(shè)計(jì)模式往往只針對(duì)某個(gè)特定場(chǎng)景。

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

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

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

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

          后來又發(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)諗坑诮涌冢徊贿^使用者需要多寫一些可能不是"太標(biāo)準(zhǔn)"的代碼。依賴于設(shè)計(jì)模式,又能獨(dú)立思考某些設(shè)計(jì)模式,這樣更有可能靈活使用設(shè)計(jì)模式。

          Python與算法社區(qū)

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

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

          手機(jī)掃一掃分享

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

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美人与性口牲恔配上海 | 高清无码视频免费看 | 强开小嫩苞A片黑人 | 97操逼网 | 亚洲色就是色 |