摘要:所以設(shè)計(jì)模式其實(shí)就是在前人各種踩坑經(jīng)驗(yàn)之上,總結(jié)出的各種開發(fā)套路。但更好的套路是使用單例模式它可以保證只創(chuàng)建一個(gè)對(duì)象第一次訪問時(shí)創(chuàng)建,之后訪問時(shí)直接返回已有對(duì)象,并提供全局的訪問。因此也有很多人對(duì)于設(shè)計(jì)模式的價(jià)值存在質(zhì)疑。
編程教室開了這么久,已經(jīng)有很多人從完全零基礎(chǔ)的小白成為了會(huì)寫代碼的菜鳥程序員,能夠自己獨(dú)立開發(fā)程序。不過到此階段,常常會(huì)遇到瓶頸,感覺功能可以實(shí)現(xiàn),但代碼看起來有些別扭:
代碼中有很多相似的重復(fù)代碼
代碼中有大量的 if,以至于有很長(zhǎng)的縮進(jìn)
單個(gè)代碼寫得很長(zhǎng),別人很難看懂,過陣子可能自己都看不懂
總會(huì)有沒有考慮到的情況導(dǎo)致 bug
修復(fù)一個(gè) bug 又會(huì)產(chǎn)生新的 bug
單個(gè)功能可以實(shí)現(xiàn),但多個(gè)功能組合在一起就理不清
如果需求發(fā)生變動(dòng),代碼修改起來很麻煩
有多種實(shí)現(xiàn)方式時(shí)不知道該用哪一種
很難和其他人協(xié)作開發(fā)
上述的問題你是不是有過類似困擾?解決的辦法其實(shí)也簡(jiǎn)單,就是堅(jiān)持“ 多寫 ”和“ 多讀 ”:
多寫代碼。很多時(shí)候你覺得不好處理,并不是因?yàn)楦呱畹膯栴},只是你對(duì)代碼的基本使用還不夠熟練。同樣的問題,踩過坑再爬出來,反復(fù)幾次自然你也知道怎么繞開了。
多讀代碼。除了自己寫,看看別人的代碼也會(huì)學(xué)到很多。包括教程里的案例、官方示例、開源項(xiàng)目的源碼等。所謂“熟讀唐詩(shī)三百首,不會(huì)作詩(shī)也會(huì)吟”嘛。
除了這兩個(gè)“笨辦法”外,還有樣?xùn)|西,對(duì)于處在這個(gè)階段的你或許有很大啟發(fā),這就是:
設(shè)計(jì)模式設(shè)計(jì)模式是對(duì)于軟件開發(fā)中常見的一些問題所總結(jié)出的解決方案,它并不關(guān)注具體的代碼怎么寫,而是 代碼的結(jié)構(gòu)應(yīng)該如何設(shè)計(jì) ,從而讓代碼 更加可靠、可讀、可重用、易于維護(hù) 。它不是一種嚴(yán)格意義上的“技術(shù)”,而是一門“經(jīng)驗(yàn)主義”,也就是開發(fā)者經(jīng)常提到的“ 最佳實(shí)踐 ”。所以設(shè)計(jì)模式其實(shí)就是在前人各種踩坑經(jīng)驗(yàn)之上,總結(jié)出的各種開發(fā)“套路”。
舉幾個(gè)常見的設(shè)計(jì)模式例子:
單例模式
場(chǎng)景舉例:代碼中需要一個(gè)共享的資源管理器,保證在代碼只有唯一的一個(gè)實(shí)例,且代碼各處都可以訪問到。
如果你的代碼只有一個(gè)文件,可能不會(huì)遇上這個(gè)問題。但當(dāng)項(xiàng)目大一點(diǎn)之后,這個(gè)問題十分常見。你可以選擇定義一些全局變量來實(shí)現(xiàn)。但更好的“套路”是使用單例模式:它可以保證 只創(chuàng)建一個(gè)對(duì)象 (第一次訪問時(shí)創(chuàng)建,之后訪問時(shí)直接返回已有對(duì)象), 并提供全局的訪問 。
代碼演示
# 單例類 class Singleton(object): _instance = None def __new__(cls, *args, **kw): if not cls._instance: cls._instance = super(Singleton, cls).__new__(cls, *args, **kw) return cls._instance # 繼承單例 class MyClass(Singleton): a = 1 # 使用 mc1 = MyClass() mc2 = MyClass() print(mc1==mc2) mc1.a += 1 print(mc2.a)
輸出
True 2
之前我們的文章《Crossin:Python單例模式(Singleton)的N種實(shí)現(xiàn)》有專門討論過 Python 中的單例模式實(shí)現(xiàn)。
工廠模式
場(chǎng)景舉例:在一個(gè)繪圖工具里,有不同的筆刷。當(dāng)點(diǎn)擊不同的筆刷按鈕時(shí),需要?jiǎng)?chuàng)建對(duì)應(yīng)的筆刷供使用。
如果把每個(gè)按鈕響應(yīng)里都去多帶帶創(chuàng)建,代碼會(huì)很冗余且不利于維護(hù)。這時(shí)可創(chuàng)建一個(gè)“工廠”類,將創(chuàng)建筆刷的代碼放在其中, 只需要根據(jù)傳入的參數(shù)不同,返回不同的筆刷實(shí)例即可 。就如同工廠根據(jù)訂單生產(chǎn)產(chǎn)品一樣。
代碼演示
# 筆刷工廠,具體類代碼略 def pen_factory(mode): if mode == "PEN": return Pen() elif mode == "PENCIL": return Pencil() elif mode == "BRUSH": return Brush() else: return None # 使用 p = pen_factory("BRUSH")
代理模式
場(chǎng)景舉例:開發(fā)一個(gè)論壇,允許用戶在帖子中上傳圖片,于是需要提供保存圖片的功能。
一般為了網(wǎng)站的訪問速度,會(huì)選擇第三方的圖片保存服務(wù)。那么在保存圖片的時(shí)候,就需要調(diào)用其提供的接口。而應(yīng)用代理模式的話,就會(huì)在網(wǎng)站和第三方服務(wù)間增加一層。這樣的好處是可以 將一些額外的處理放在代理層中 ,當(dāng)需要更換第三方服務(wù)時(shí), 不需要修改網(wǎng)站的邏輯 ,只要調(diào)整代理層即可。
代碼演示
class ImgService: @abstractmethod def save(self, img): pass # 真實(shí)類 class XYZImgService(ImgService): def save(self, img): # 調(diào)用第三方服務(wù)接口 # 代理類 class ImgServiceProxy(ImgService): def __init__(self): self.service = XYZImgService() def save(self, img): return self.service.save(img) # 使用 def save_img(img): proxy = ImgServiceProxy() proxy.save(img)
設(shè)計(jì)模式的 六大原則 :
1、 開閉原則 (Open Close Principle)
對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉。在需求變動(dòng)時(shí),盡可能不修改原有代碼,而通過擴(kuò)展實(shí)現(xiàn)。
2、 里氏代換原則 (Liskov Substitution Principle)
在使用繼承時(shí),在子類中盡量不要重寫和重載父類的方法。
3、 依賴倒轉(zhuǎn)原則 (Dependence Inversion Principle)
針對(duì)接口編程,細(xì)節(jié)依賴于抽象。
4、 接口隔離原則 (Interface Segregation Principle)
降低類之間的耦合度,不依賴不必要的接口。
5、 迪米特法則 ,又稱 最少知道原則 (Demeter Principle)
模塊之間相互獨(dú)立,對(duì)自己依賴的類需要知道的信息越少越好。
6、 合成復(fù)用原則 (Composite Reuse Principle)
盡量使用合成/聚合的方式,而不是使用繼承。
具體的解讀,今天沒法在一篇推送中展開詳述,而且這是個(gè)需要不斷體會(huì)和實(shí)踐的事情。首先你可以找些相關(guān)書籍讀一讀。設(shè)計(jì)模式有一本經(jīng)典書籍:《 Design Patterns: Elements of Reusable Object-Oriented Software 》(《設(shè)計(jì)模式:可復(fù)用面向?qū)ο筌浖幕A(chǔ)》)。此書又被稱作“ GoF ”(Gang of Four,四人組),四位業(yè)內(nèi)大牛總結(jié)出了 23 種設(shè)計(jì)模式。
然而,我強(qiáng)烈 不 推薦新手去看這本書,因?yàn)槟愫芸赡芸床欢N彝扑]的是一本叫做《 Head first 設(shè)計(jì)模式 》的書,可以算作上面那本的白話入門版,對(duì)于新手來說友好許多,或許幫助更大。
開發(fā)者對(duì)于設(shè)計(jì)模式的理解大致存在這樣幾個(gè)階段:一開始只關(guān)注語(yǔ)法和庫(kù), 不懂設(shè)計(jì)模式 ,寫代碼無章法;后來了解了設(shè)計(jì)模式之后,開始嘗試 套用設(shè)計(jì)模式 ,懂得重構(gòu)代碼,但有時(shí)難免教條化或陷入過度設(shè)計(jì)的誤區(qū);等到開發(fā)經(jīng)驗(yàn)豐富之后, 不再拘泥于所謂的“模式” ,本身寫出的代碼就已經(jīng)契合設(shè)計(jì)的原則。
書上的設(shè)計(jì)模式是一成不變的,不可能涵蓋每一種開發(fā)場(chǎng)景,而軟件技術(shù)本身也不斷發(fā)展,很多模式已經(jīng)被新的語(yǔ)言特性所實(shí)現(xiàn)。因此也有很多人對(duì)于設(shè)計(jì)模式的價(jià)值存在質(zhì)疑。我的看法是,如果你處在新手階段, 學(xué)習(xí)設(shè)計(jì)模式是很好的提升方式 ,也可以開拓你的編程思維。而當(dāng)你已經(jīng)走上進(jìn)階之路之后, 更多的應(yīng)是關(guān)注模式背后的原則 ,寫出更合理的代碼,而并非為了模式而模式。
當(dāng)然這一切,還是都離不開足夠的代碼量。每個(gè)程序員都是一行行代碼堆出來。
════
其他文章及回答:
學(xué)編程:如何自學(xué)Python | 新手引導(dǎo) | 一圖學(xué)Python
開發(fā)案例:智能防擋彈幕 | 紅包提醒 | 流浪地球
歡迎搜索及關(guān)注: Crossin的編程教室
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/43238.html
摘要:我們應(yīng)該寫一段拓展性強(qiáng)與維護(hù)性較強(qiáng)的代碼,由此衍生出觀察者模式。 該文章屬于《編程中的那些經(jīng)典套路——設(shè)計(jì)模式匯總》系列,并且以下內(nèi)容基于語(yǔ)言PHP 今天我們來談?wù)動(dòng)^察者模式,這是一個(gè)經(jīng)常用到的設(shè)計(jì)模式。 讓我們想象一個(gè)場(chǎng)景:一個(gè)網(wǎng)站有不同等級(jí)區(qū)域的用戶,不同等級(jí)的的用戶登錄后可以獲得對(duì)應(yīng)的服務(wù)(一級(jí)用戶登錄后獲得一級(jí)服務(wù),二級(jí)用戶登錄后獲得二級(jí)服務(wù),…以此類推)。那么我們?nèi)绾螌戇@段業(yè)...
摘要:如果看不懂的話,可以在評(píng)論區(qū)中提問,我會(huì)第一時(shí)間回答你無論何時(shí)我一直都在嗯哼該文章屬于編程中的那些經(jīng)典套路設(shè)計(jì)模式匯總系列 在正式閱讀前,我先談?wù)勎覀冊(cè)撚檬裁醋藙?shì)和心態(tài)學(xué)習(xí)設(shè)計(jì)模式: 如果你還沒有過多的編程經(jīng)驗(yàn)(泛指半年以下),我建議你把它當(dāng)做小說來看,能看懂多少是多少,因?yàn)榘肽暌韵陆?jīng)驗(yàn)的程序員用到設(shè)計(jì)模式的情況只會(huì)出現(xiàn)在面試上,至于實(shí)際工作中?相對(duì)來說這部分不會(huì)由你負(fù)責(zé)。 如果你已...
該文章屬于《編程中的那些經(jīng)典套路——設(shè)計(jì)模式匯總》系列,并且以下內(nèi)容基于語(yǔ)言PHP 今天我們來談?wù)勥m配器模式。 想象一個(gè)場(chǎng)景: 有一個(gè)類方法它部署在服務(wù)器上,專門負(fù)責(zé)大多數(shù)語(yǔ)言都通用的JSON語(yǔ)言,而現(xiàn)在我需要調(diào)用這個(gè)類方法,但我不需要返回JSON格式的數(shù)據(jù)了,我要返回序列化后的數(shù)據(jù),我現(xiàn)在如何處理呢?是上去服務(wù)器修改這個(gè)類方法嗎?這不科學(xué)吧?因?yàn)槲覀冊(cè)揪帉懞玫拇a最好就不要再改了,很容易造成...
該文章屬于《編程中的那些經(jīng)典套路——設(shè)計(jì)模式匯總》系列,并且以下內(nèi)容基于語(yǔ)言PHP 今天我們來談?wù)勓b飾器模式,想象一個(gè)場(chǎng)景: 有一篇帖子 帖子的內(nèi)容我寫好了, 三個(gè)部門的人員想控制它. 編輯組要添導(dǎo)讀文字 審核組要去敏感字 市場(chǎng)部想在末尾加點(diǎn)廣告 我只是一篇帖子,由你們來處置吧。 此時(shí)如何處理呢?如何寫出符合面向?qū)ο笕匦晕逶瓌t的代碼呢?由此引出裝飾器模式就發(fā)揮作用了 一言不合來看看代碼: 裝...
該文章屬于《編程中的那些經(jīng)典套路——設(shè)計(jì)模式匯總》系列,并且以下內(nèi)容基于語(yǔ)言PHP 今天來談?wù)勜?zé)任鏈模式,乍一聽責(zé)任鏈模式好像很高級(jí)的一樣,但是相信我,其實(shí)每位天朝的同學(xué)都十分熟悉這個(gè)模式,責(zé)任鏈模式,就好像中國(guó)的官場(chǎng)制度一樣,每一個(gè)級(jí)別的權(quán)利都區(qū)分的很細(xì),舉個(gè)生活中的栗子: 村委不能越級(jí)去替鎮(zhèn)委辦事情,如果村委無法解決,只能向上求助鎮(zhèn)委 鎮(zhèn)委不能越級(jí)去替市委辦事情,如果鎮(zhèn)委無法解決,只能向上求...
閱讀 3686·2021-10-11 11:09
閱讀 1349·2021-09-24 10:35
閱讀 3441·2021-07-29 13:48
閱讀 474·2019-08-30 13:15
閱讀 2526·2019-08-30 12:53
閱讀 3228·2019-08-30 12:44
閱讀 2720·2019-08-29 16:57
閱讀 970·2019-08-29 12:26