內(nèi)容簡介:干啥事情都有套路,編程序也是一樣鳍寂。Design Pattern就是這樣一種技術(shù),由經(jīng)驗豐富的程序員總結(jié)出來彻舰,把各種應用場景下的面向?qū)ο笤O計套路給抽象出來伐割。類似于孫子兵法,但是任何模式都不是萬能的刃唤,還是要活學活用才能事半功倍隔心,今天就我知道的一點皮毛,來隨便聊聊尚胞。
1硬霍、什么是設計模式
在你學習如何編寫Python程序后,你肯定會為進入這個生態(tài)而興奮笼裳,因為又太多的開源代碼可以去使用唯卖,但是如果你遇到一個開源軟件的代碼,即使你懂得全部的語法仍然看不懂這些代碼的含義(筆者在閱讀概率編程PyMC3包的源碼時就感到這種無力感)躬柬,或者當你設計自己軟件到一定程度時拜轨,發(fā)現(xiàn)代碼越寫越復雜,Bug越來越難以維護允青,軟件性能提高遇到瓶頸橄碾,多人協(xié)作不起來,這時候就體現(xiàn)出要如何成為一個專業(yè)的軟件設計者了。
而要成為專業(yè)的軟件設計者法牲,對已有設計模式的學習應該是第一門必修課史汗。
設計模式是對設計原則的具體化。用江湖話說就是武林秘籍拒垃,總結(jié)出來的一些固定套路停撞,可以幫助有根基的程序員迅速打通任督二脈,從此做什么都特別快悼瓮。
面向?qū)ο蟪绦蛟O計與傳統(tǒng)的面向過程程序設計不同戈毒,對系統(tǒng)設計者需要從OO角度思考如何設計,否則系統(tǒng)越復雜軟件的維護越困難谤牡,多人協(xié)同開發(fā)也變地非常低效副硅。
2、設計原則
通常OPP七大設計原則如下:
1.單一職責原則(Single Responsiblity Principle, SRP)
一個類負責一項職責翅萤。2.開閉原則(Open Closed Principle, OCP)
一個軟件實體如類恐疲、模塊和函數(shù)應該對擴展開放,對修改關(guān)閉套么。3.里氏替換原則(Liskov Substitution Principle, LSP)
繼承與派生的規(guī)則(子類可替換父類)4.依賴倒轉(zhuǎn)原則(Dependency Inversion Principle, DIP)
高層模塊不應該依賴低層模塊培己,二者都應該依賴其抽象;抽象不應該依賴細節(jié)胚泌;細節(jié)應該依賴抽象省咨。即針對接口編程,不要針對實現(xiàn)編程玷室。5.接口隔離原則(Interface Segregation Principle, ISP)
建立單一接口零蓉,不要建立龐大臃腫的接口,盡量細化接口穷缤,接口中的方法盡量少敌蜂。6.組合/聚合復用原則(Composite/Aggregate Reuse Principle, CARP)
盡量使用組合和聚合少使用繼承的關(guān)系來達到復用的原則。7.最小知識原則(迪米特法則)(Principle of Least Knowledge, PLK)
高內(nèi)聚津肛,低耦合(high cohesion low coupling)章喉。
要學好面向?qū)ο缶幊蹋枰私庠O計模式身坐。
設計模式是經(jīng)過總結(jié)秸脱、優(yōu)化的,對我們經(jīng)常會碰到的一些編程問題的可重用解決方案部蛇。一個設計模式并不像一個類或一個庫那樣能夠直接作用于我們的代碼摊唇。反之,設計模式更為高級涯鲁,它是一種必須在特定情形下實現(xiàn)的一種方法模板巷查。設計模式不會綁定具體的編程語言嘹害。一個好的設計模式應該能夠用大部分編程語言實現(xiàn)(如果做不到全部的話,具體取決于語言特性)吮便。最為重要的是,設計模式也是一把雙刃劍幢踏,如果設計模式被用在不恰當?shù)那樾蜗聦斐蔀碾y髓需,進而帶來無窮的麻煩。然而如果設計模式在正確的時間被用在正確地地方房蝉,它將是你的救星僚匆。
起初,你會認為“模式”就是為了解決一類特定問題而特別想出來的明智之舉搭幻。說的沒錯咧擂,看起來的確是通過很多人一起工作,從不同的角度看待問題進而形成的一個最通用檀蹋、最靈活的解決方案松申。也許這些問題你曾經(jīng)見過或是曾經(jīng)解決過,但是你的解決方案很可能沒有模式這么完備俯逾。
雖然被稱為“設計模式”贸桶,但是它們同“設計“領(lǐng)域并非緊密聯(lián)系。設計模式同傳統(tǒng)意義上的分析桌肴、設計與實現(xiàn)不同皇筛,事實上設計模式將一個完整的理念根植于程序中,所以它可能出現(xiàn)在分析階段或是更高層的設計階段坠七。很有趣的是因為設計模式的具體體現(xiàn)是程序代碼水醋,因此可能會讓你認為它不會在具體實現(xiàn)階段之前出現(xiàn)(事實上在進入具體實現(xiàn)階段之前你都沒有意識到正在使用具體的設計模式)。
可以通過程序設計的基本概念來理解模式:增加一個抽象層彪置。抽象一個事物就是隔離任何具體細節(jié)拄踪,這么做的目的是為了將那些不變的核心部分從其他細節(jié)中分離出來。當你發(fā)現(xiàn)你程序中的某些部分經(jīng)常因為某些原因改動悉稠,而你不想讓這些改動的部分引發(fā)其他部分的改動宫蛆,這時候你就需要思考那些不會變動的設計方法了。這么做不僅會使代碼可維護性更高的猛,而且會讓代碼更易于理解耀盗,從而降低開發(fā)成本。
一般可以分為三種最基本的設計模式:
創(chuàng)建模式卦尊,提供實例化的方法叛拷,為適合的狀況提供相應的對象創(chuàng)建方法。創(chuàng)建型模式(Creational Pattern)對類的實例化過程進行了抽象岂却,能夠?qū)④浖K中對象的創(chuàng)建和對象的使用分離忿薇。為了使軟件的結(jié)構(gòu)更加清晰裙椭,外界對于這些對象只需要知道它們共同的接口,而不清楚其具體的實現(xiàn)細節(jié)署浩,使整個系統(tǒng)的設計更加符合單一職責原則揉燃。
創(chuàng)建型模式在創(chuàng)建什么(What),由誰創(chuàng)建(Who)筋栋,何時創(chuàng)建(When)等方面都為軟件設計者提供了盡可能大的靈活性炊汤。創(chuàng)建型模式隱藏了類的實例的創(chuàng)建細節(jié),通過隱藏對象如何被創(chuàng)建和組合在一起達到使整個系統(tǒng)獨立的目的弊攘。
結(jié)構(gòu)化模式抢腐,通常用來處理實體之間的關(guān)系,使得這些實體能夠更好地協(xié)同工作襟交。結(jié)構(gòu)型模式(Structural Pattern)描述如何將類或者對象結(jié)合在一起形成更大的結(jié)構(gòu)迈倍,就像搭積木,可以通過簡單積木的組合形成復雜的捣域、功能更為強大的結(jié)構(gòu)啼染。
結(jié)構(gòu)型模式可以分為類結(jié)構(gòu)型模式和對象結(jié)構(gòu)型模式:
類結(jié)構(gòu)型模式關(guān)心類的組合,由多個類可以組合成一個更大的系統(tǒng)竟宋,在類結(jié)構(gòu)型模式中一般只存在繼承關(guān)系和實現(xiàn)關(guān)系提完。對象結(jié)構(gòu)型模式關(guān)心類與對象的組合,通過關(guān)聯(lián)關(guān)系使得在一個類中定義另一個類的實例對象丘侠,然后通過該對象調(diào)用其方法徒欣。根據(jù)“合成復用原則”,在系統(tǒng)中盡量使用關(guān)聯(lián)關(guān)系來替代繼承關(guān)系蜗字,因此大部分結(jié)構(gòu)型模式都是對象結(jié)構(gòu)型模式打肝。
行為模式,用于在不同的實體間進行通信挪捕,為實體之間的通信提供更容易粗梭,更靈活的通信方法。
行為型模式(Behavioral Pattern)是對在不同的對象之間劃分責任和算法的抽象化级零。行為型模式不僅僅關(guān)注類和對象的結(jié)構(gòu)断医,而且重點關(guān)注它們之間的相互作用。通過行為型模式奏纪,可以更加清晰地劃分類與對象的職責鉴嗤,并研究系統(tǒng)在運行時實例對象之間的交互。在系統(tǒng)運行時序调,對象并不是孤立的醉锅,它們可以通過相互通信與協(xié)作完成某些復雜功能,一個對象在運行時也將影響到其他對象的運行发绢。
行為型模式分為類行為型模式和對象行為型模式兩種:
類行為型模式:類的行為型模式使用繼承關(guān)系在幾個類之間分配行為硬耍,類行為型模式主要通過多態(tài)等方式來分配父類與子類的職責垄琐。
對象行為型模式:對象的行為型模式則使用對象的聚合關(guān)聯(lián)關(guān)系來分配行為,對象行為型模式主要是通過對象關(guān)聯(lián)等方式來分配兩個或多個類的職責经柴。根據(jù)“合成復用原則”狸窘,系統(tǒng)中要盡量使用關(guān)聯(lián)關(guān)系來取代繼承關(guān)系,因此大部分行為型設計模式都屬于對象行為型設計模式坯认。
第一大類:創(chuàng)建型(6種)
Factory Method(工廠方法)定義了一個創(chuàng)建對象的接口, 但由子類決定要實例化的類是哪一個朦前。工廠方法讓類把實例化推遲到子類。
Abstract Factory(抽象工廠)提供一個接口鹃操,用于創(chuàng)建相關(guān)或依賴對象的家族, 而不需要指定具體類。
Builder(生成器)使用生成器模式封裝一個產(chǎn)品的構(gòu)造過程, 并允許按步驟構(gòu)造春哨。將一個復雜對象的構(gòu)建與它的表示分離, 使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示荆隘。
Prototype(原型)當創(chuàng)建給定類的實例過程很昂貴或很復雜時, 就使用原形模式。
Singleton(單例)確保一個類只有一個實例, 并提供全局訪問點赴背。
Multiton pattern (多例模式) 在一個解決方案中結(jié)合兩個或多個模式, 以解決一般或重復發(fā)生的問題椰拒。
第二大類:結(jié)構(gòu)型(7種)
Adapter Class/Object(適配器)將一個類的接口, 轉(zhuǎn)換成客戶期望的另一個接口。 適配器讓原本接口不兼容的類可以合作無間. 對象適配器使用組合, 類適配器使用多重繼承凰荚。
Bridge(橋接)使用橋接模式通過將實現(xiàn)和抽象放在兩個不同的類層次中而使它們可以獨立改變燃观。
Composite(組合)允許你將對象組合成樹形結(jié)構(gòu)來表現(xiàn)”整體/部分”層次結(jié)構(gòu)。組合能讓客戶以一致的方式處理個別對象以及對象組合便瑟。
Decorator(裝飾)動態(tài)地將責任附加到對象上, 若要擴展功能, 裝飾者提供了比繼承更有彈性的替代方案缆毁。
Facade(外觀)提供了一個統(tǒng)一的接口, 用來訪問子系統(tǒng)中的一群接口。外觀定義了一個高層接口, 讓子系統(tǒng)更容易使用到涂。
Flyweight(享元)如想讓某個類的一個實例能用來提供許多”虛擬實例”, 就使用該模式脊框。
Proxy(代理)為另一個對象提供一個替身或占位符以控制對這個對象的訪問.。
第三大類:行為型(11種)
Interpreter(解釋器)使用解釋器模式為語言創(chuàng)建解釋器践啄。
Template Method(模板方法)在一個方法中定義一個算法的骨架, 而將一些步驟延遲到子類中浇雹。模板方法使得子類可以在不改變算法結(jié)構(gòu)的情況下, 重新定義算法中的某些步驟。
Chain of Responsibility(責任鏈)通過責任鏈模式, 你可以為某個請求創(chuàng)建一個對象鏈.屿讽。每個對象依序檢查此請求并對其進行處理或者將它傳給鏈中的下一個對象昭灵。
Command(命令)將”請求”封閉成對象, 以便使用不同的請求,隊列或者日志來參數(shù)化其他對象. 命令模式也支持可撤銷的操作。
Iterator(迭代器)提供一種方法順序訪問一個聚合對象中的各個元素, 而又不暴露其內(nèi)部的表示伐谈。
Mediator(中介者)使用中介者模式來集中相關(guān)對象之間復雜的溝通和控制方式烂完。
Memento(備忘錄)當你需要讓對象返回之前的狀態(tài)時(例如, 你的用戶請求”撤銷”), 你使用備忘錄模式。
Observer(觀察者)在對象之間定義一對多的依賴, 這樣一來, 當一個對象改變狀態(tài), 依賴它的對象都會收到通知, 并自動更新衩婚。
State(狀態(tài))允許對象在內(nèi)部狀態(tài)改變時改變它的行為, 對象看起來好象改了它的類窜护。
Strategy(策略)定義了算法族, 分別封閉起來, 讓它們之間可以互相替換, 此模式讓算法的變化獨立于使用算法的客戶。
Visitor(訪問者)當你想要為一個對象的組合增加新的能力, 且封裝并不重要時, 就使用訪問者模式非春。
以上抽象的總結(jié)很難一下子理解好柱徙,設計模式都是有從事多年軟件設計的專業(yè)人士從無數(shù)項目實例中總結(jié)得來缓屠,對于沒有實踐的初學者,只要先知道這些設計模式分類即可护侮。