設計模式是不是有點太玄了?

最近在看《設計模式解析-第二版》這本書,看的有點吃力,作者本身對設計模式也不是很迷信,還有些人用「一千個人中,有一千個哈姆雷特」形容設計模式,那到底有沒有設計模式,那23種設計模式是不是有些炒作的太玄了。


一點都不玄。

設計模式是無數碼農前人在實際的生產項目中經過不斷的踩坑、爬坑、修坑的經歷總結出來的經驗教訓,經過抽象之後表達成的概念。能夠幫助後來的設計者避免重複同樣的錯誤或者彎路。

你覺得不好理解,實際上並不是你看不懂,而是你不明白為何要如此「故弄玄虛"。這個很好明白,等你真正經歷大型項目開發、迭代、重構、甚至重寫之後,你就會贊同這些能寫出設計模式的人,是多麼的高瞻遠矚,多麼的有智慧。

一言以蔽之,設計模式的本質就是一句話:將軟體中變化的部分和不變的部分分開。


那到底有沒有設計模式,那23種設計模式是不是有些炒作的太玄了。

設計模式當然有了,一點都不玄。如果你學會了,每天編程幾乎每時每刻都會遇到、用到,就像那些經典的數據結構和演算法,家常便飯。

以 GoF 為代表的經典設計模式,是編程高手們日常的一種編程方式,也是一種客觀存在。大家之所以推崇設計模式,是因為 20 年前 1990 年代中期,當時正好是編程主流、範式從傳統結構化編程到 OO 編程轉變、OO 編程語言(C++、Java)興起的關鍵時期,而 GoF 名著的問世可謂生逢其時,在軟體工程與編程史上具有開創性和里程碑意義。

不過我不建議初學者學設計模式一開始就讀 GoF 的原著,這書偏難,內容太老,有點過時了。

如今 20 年過去了,設計模式早已成為稀鬆平常的編程技術,中高級程序猿都應該而且已經掌握,進入普通大學教材也理所應當。

你認為玄,是因為你目前的編程水平還不夠(屬於初級吧),抽象思維和邏輯思維欠缺,尤其對 OOAD、OOP中涉及到的一些常見編程問題與技巧(如,如何應對變化)等缺乏了解和認知,對OO編程語言的一些特點和精髓也缺乏了解,所以無法理解這些設計模式的精妙所在。

國內外江湖對設計模式可能有吹捧炒作的成分,這主要涉及到軟體技術媒體的商業利益,例如賣書促銷。


很玄,不然你以為那麼多碼農很喜歡重構是為了什麼?

也不玄,不然你以為為什麼有那麼多碼農能發現自己代碼結構中不合理的地方而去重構?


設計模式就是前人對代碼設計方法的經驗總結而已,使用設計模式可以讓你的代碼變得更加可維護、易於擴展。

下面是我對各種設計模式的理解的一句話總結(可以點擊設計模式名稱進入查看詳細內容~)。

希望對你有幫助~

創建型模式

這些設計模式提供了一種在創建對象的同時隱藏創建邏輯的方式,而不是使用新的運算符直接實例化對象。這使得程序在判斷針對某個給定實例需要創建哪些對象時更加靈活。

  • 工廠模式與抽象工廠模式 (Factory Pattern)(Abstract Factory Pattern):不同條件下創建不同實例

  • 單例模式 (Singleton Pattern):保證一個類僅有一個實例

  • 建造者模式 (Builder Pattern)將一個複雜的構建過程與其具表示細節相分離,使得同樣的構建過程可以創建不同的表示

  • 原型模式 (Prototype Pattern)通過拷貝原型創建新的對象

結構型模式

這些設計模式關注類和對象的組合。

  • 適配器模式 (Adapter Pattern)使得原本由於介面不兼容而不能一起工作的那些類可以一起工作

  • 裝飾器模式 (Decorator Pattern)保持介面,增強性能:修飾類繼承被修飾對象的抽象父類,依賴被修飾對象的實例(被修飾對象依賴注入),以實現介面擴展

  • 橋接模式 (Bridge Pattern)兩個維度獨立變化,依賴方式實現抽象與實現分離:需要一個作為橋接的介面/抽象類,多個角度的實現類依賴注入到抽象類,使它們在抽象層建立一個關聯關係

  • 外觀模式 (Facade Pattern)在客戶端和複雜系統之間再加一層,這一次將調用順序、依賴關係等處理好。即封裝底層實現,隱藏系統的複雜性,並向客戶端提供了一個客戶端可以訪問系統的高層介面

  • 代理模式 (Proxy Pattern)為其他對象提供一種代理以控制對這個對象的訪問:增加中間層(代理層),代理類與底層實現類實現共同介面,並創建底層實現類對象(底層實現類對象依賴注入代理類),以便向外界提供功能介面

  • 過濾器模式 (Filter、Criteria Pattern)使用不同的標準來過濾一組對象,通過邏輯運算以解耦的方式把它們連接起來

  • 組合模式 (Composite Pattern)用戶對單個對象和組合對象的使用具有一致性的統一介面

  • 享元模式 (Flyweight Pattern)享元工廠類控制;HashMap實現緩衝池重用現有的同類對象,如果未找到匹配的對象,則創建新對象

行為型模式

這些設計模式特別關注對象之間的通信。

  • 責任鏈模式(Chain of Responsibility Pattern)攔截的類都實現統一介面,每個接收者都包含對下一個接收者的引用。將這些對象連接成一條鏈,並且沿著這條鏈傳遞請求,直到有對象處理它為止。

  • 觀察者模式(Observer Pattern)一對多的依賴關係,在觀察目標類里有一個 ArrayList 存放觀察者們。當觀察目標對象的狀態發生改變,所有依賴於它的觀察者都將得到通知,使這些觀察者能夠自動更新(即使用推送方式)

  • 模板模式(Template Pattern)將這些通用演算法抽象出來,在一個抽象類中公開定義了執行它的方法的方式/模板。它的子類可以按需要重寫方法實現,但調用將以抽象類中定義的方式進行

  • 命令模式(Command Pattern)將"行為請求者"與"行為實現者"解耦:調用者依賴命令,命令依賴接收者,調用者Invoker→命令Command→接收者Receiver

  • 解釋器模式(Interpreter Pattern):給定一個語言,定義它的文法表示,並定義一個解釋器,這個解釋器使用該標識來解釋語言中的句子

  • 迭代器模式(Iterator Pattern):集合中含有迭代器:分離了集合對象的遍歷行為,抽象出一個迭代器類來負責,無須暴露該對象的內部表示

  • 中介者模式(Mediator Pattern)對象與對象之間存在大量的關聯關係,將對象之間的通信關聯關係封裝到一個中介類中單獨處理,從而使其耦合鬆散,可以獨立地改變它們之間的交互

  • 策略模式(Strategy Pattern)策略對象依賴注入到context對象,context對象根據它的策略改變而改變它的相關行為(可通過調用內部的策略對象實現相應的具體策略行為)

  • 狀態模式(State Pattern)狀態對象依賴注入到context對象,context對象根據它的狀態改變而改變它的相關行為(可通過調用內部的狀態對象實現相應的具體行為)

  • 備忘錄模式(Memento Pattern):通過一個備忘錄類專門存儲對象狀態。客戶通過備忘錄管理類管理備忘錄類。

  • 空對象模式(Null Object Pattern):創建一個未對該類做任何實現的空對象類,該空對象類將無縫地使用在需要檢查空值的地方。不要為了屏蔽null而使用空對象,應保持用null,遠比用非null的值來替代「無值」要好。(慎用)


軟體設計是工科,是一門以實踐為基礎的學問,不去具體做工作寫項目,單憑讀書是很難學好的。


《三十六計》玄不玄?也玄!那兩三千年來世界其他國家沒看過&<三十六計&>是怎麼打仗的?照樣打。沒學過三十六計的人就不會使用裡面的計策嗎?當然會用,而且經常用。只是你不知道古代已經把它總結成「戰爭模式」了。比如「借刀殺人」,相信這個人們在耍小聰明的時候都用過;「打草驚蛇」這個計策估計連小孩都會用,還有很多。三十六計是我們平時經常用但是不知道這個已經被古人總結成了「模式」。同樣的道理,你沒學過設計模式就沒有使用過嗎?非也!你也一樣經常用到,只是你不知道前人已經寫成書,甚至發表論文了。比如你用struts或springmvc的時候,其實你已經用了mvc模式了。你在寫共享一個實例的時候你已經用到了單例模式,當你想要對某個功能擴展時你可能已經用到了wrapper模式,當你想要兼容時可能已經用到了適配器模式,當你組合某個控制項時你已經用到了組合模式等等,設計模式雖然名字很玄,並且可能你沒看過相關的書籍,但不代表你沒有用過。


對於 10w 行以下的代碼量的漢子來說,設計模式=玄學。

對於 10w ~ 50w 行代碼量的漢子來說,設計模式=科學。

對於 50w 行以上代碼量的漢子來說,設計模式=文學。


不玄,你把它理解得太玄了


一點也不玄

用咱老百姓的話講就是套路

懂點套路你能避免被坑

不懂套路那就只好回農村

自從快手火起來以後農村現在套路也不少

哭。。。


還是很有用的,多數人是寫不出牛逼的演算法的,所以,學學設計模式多寫點高質量易維護的代碼,也算是積德行善了。


先說結論:設計模式並不玄,本質上是一些對面向對象語言特性(抽象和多態)的用法

當然,有些用法確實比較巧妙。如果把編程比作下棋,設計模式就是一些圍棋定式。正如理解定式先要了解圍棋規則的本質,要理解設計模式的話,就應該了解面向對象語言特性的本質。

面向對象語言被創造出來本質上是來解決語言級別的復用問題的。而具體方式就是抽象和多態。由於有了類的繼承結構(抽象),大段的條件判斷代碼只需要用簡潔的一句方法調用就好了。面向對象語言的特性能夠讓編譯器推斷出潛在的條件判斷,從而減少程序代碼的書寫量。從這個角度來講,繼承和多態特性所減少的代碼,一定是條件判斷的代碼。

因此,面對各種各樣的問題,可以利用這種特性來組織代碼結構(也就是設計代碼結構),儘可能多地讓編譯器來推理出條件判斷而非自己顯示地書寫條件判斷。達到這一目的設計,代碼也會變得相對簡潔。所以,吃透這種特性,可以根據各種實際情況創造屬於自己的設計模式

============================================

多說一句,復用性和代碼的可理解性往往存在制約關係,換言之,復用率過高的代碼往往並不好理解,所以在項目中頻繁使用設計模式可能會帶來理解性問題。因此,好的設計需要反覆權衡。我個人的想法是:如果二者不可得兼,舍復用性而取理解性者也。


Patterns mean "I"ve run out of language."


你沒有看出設計模式的好處是因為你代碼量不夠。

要是只是做過學校的實驗,寫寫排序當然沒必要用設計模式,題主報代碼量。

還有個人建議設計模式這種書不適合入門級選手。


沒有,設計模式的核心就兩個字:解耦。

具體的模式只是給你提供了現成的框架,萬變不離其宗。


簡單的說,設計模式就是教你哪些場景下的設計需要封裝哪些變化,如何封裝。


當你遇到大型項目需要對許多功能進行解耦時,當你面對頻繁的需求更改時,當你遇到幾十人甚至上百人的開發團隊需要各司其職並且還能保持項目的統一時,你就知道設計模式是多麼重要的思想。


自己整理出幾個寫代碼的原則:

1.原子化模塊,類,函數。

2.需要時調用。

3.想問題多想一步,別想得太簡單,考慮更多的情況與情景。

基於以上的原則,在寫代碼的時候遇到問題多思考,可以自己構建出適合的設計模式,有些是與書上的模式不謀而合,有些是書上的幾個模式的組合。

總體上來說:需要自己有思考的能力,哪怕沒有理論,你也可以自己做的更好。另一方面就是有各種項目經驗,才會遇到各種架構方面的問題,自己思考過後再去看書,才有「原來如此」的會心一笑。


在確定需求之前,再好的模式也是白搭了


從無模式到有模式再到無模式。

世界上本沒有模式,更沒有單純的模式,可以說是有多個模式複合的情況,但是模式僅僅是一種認識上的抽象,不是世界存在的邏輯和規則。

當你心中無模式的時候,就成高手了。


等你把一個項目按你的想法寫得大到覺得它快爆炸之後,你就覺得設計模式有多有用了。。。


推薦閱讀:

形式化方法(軟體可靠性方法)在實際工作中如何應用?
大學期間,想要參加一些有含金量的競賽和項目,大佬們可不可以給出一些建議和自己的學習經歷?
華南農業大學的軟體工程怎麼樣?
頭文件的包含順序問題?

TAG:軟體 | 程序員 | 編程 | 軟體工程 | 設計模式 |