寫代碼也有「套路」-談談設計模式

編程教室開了這麼久,已經有不少人從徹底零基礎的小白成爲了會寫代碼的菜鳥程序員,可以本身獨立開發程序。不過到此階段,經常會遇到瓶頸,感受功能能夠實現,但代碼看起來有些彆扭:程序員

代碼中有不少類似的重複代碼
代碼中有大量的 if,以致於有很長的縮進
單個代碼寫得很長,別人很難看懂,過陣子可能本身都看不懂
總會有沒有考慮到的狀況致使 bug
修復一個 bug 又會產生新的 bug
單個功能能夠實現,但多個功能組合在一塊兒就理不清
若是需求發生變更,代碼修改起來很麻煩
有多種實現方式時不知道該用哪種
很難和其餘人協做開發
上述的問題你是否是有過相似困擾?解決的辦法其實也簡單,就是堅持「多寫」和「多讀」:面試

多寫代碼。不少時候你以爲很差處理,並非由於高深的問題,只是你對代碼的基本使用還不夠熟練。一樣的問題,踩過坑再爬出來,反覆幾回天然你也知道怎麼繞開了。
多讀代碼。除了本身寫,看看別人的代碼也會學到不少。包括教程裏的案例、官方示例、開源項目的源碼等。所謂「熟讀唐詩三百首,不會做詩也會吟」嘛。
除了這兩個「笨辦法」外,還有樣東西,對於處在這個階段的你或許有很大啓發,這就是:編程

設計模式

設計模式是對於軟件開發中常見的一些問題所總結出的解決方案,它並不關注具體的代碼怎麼寫,而是代碼的結構應該如何設計,從而讓代碼更加可靠、可讀、可重用、易於維護。它不是一種嚴格意義上的「技術」,而是一門「經驗主義」,也就是開發者常常提到的「最佳實踐」。因此設計模式其實就是在前人各類踩坑經驗之上,總結出的各類開發「套路」。設計模式

舉幾個常見的設計模式例子:性能優化

單例模式架構

場景舉例:代碼中須要一個共享的資源管理器,保證在代碼只有惟一的一個實例,且代碼各處均可以訪問到。併發

若是你的代碼只有一個文件,可能不會趕上這個問題。但當項目大一點以後,這個問題十分常見。你能夠選擇定義一些全局變量來實現。但更好的「套路」是使用單例模式:它能夠保證只建立一個對象(第一次訪問時建立,以後訪問時直接返回已有對象),並提供全局的訪問。分佈式

代碼演示微服務

# 單例類

    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

工廠模式

場景舉例:在一個繪圖工具裏,有不一樣的筆刷。當點擊不一樣的筆刷按鈕時,須要建立對應的筆刷供使用。高併發

若是把每一個按鈕響應裏都去單首創建,代碼會很冗餘且不利於維護。這時可建立一個「工廠」類,將建立筆刷的代碼放在其中,只須要根據傳入的參數不一樣,返回不一樣的筆刷實例便可。就如同工廠根據訂單生產產品同樣。

代碼演示

筆刷工廠,具體類代碼略

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')

代理模式

場景舉例:開發一個論壇,容許用戶在帖子中上傳圖片,因而須要提供保存圖片的功能。

通常爲了網站的訪問速度,會選擇第三方的圖片保存服務。那麼在保存圖片的時候,就須要調用其提供的接口。而應用代理模式的話,就會在網站和第三方服務間增長一層。這樣的好處是能夠將一些額外的處理放在代理層中,當須要更換第三方服務時,不須要修改網站的邏輯,只要調整代理層便可。

代碼演示

class ImgService:
        @abstractmethod
        def save(self, img):
            pass

# 真實類

    class XYZImgService(ImgService):
        def save(self, img):
            # 調用第三方服務接口

# 代理類
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)

設計模式的六大原則:

一、開閉原則(Open Close Principle)
對擴展開放,對修改關閉。在需求變更時,儘量不修改原有代碼,而經過擴展實現。

二、里氏代換原則(Liskov Substitution Principle)
在使用繼承時,在子類中儘可能不要重寫和重載父類的方法。

三、依賴倒轉原則(Dependence Inversion Principle)
針對接口編程,細節依賴於抽象。

四、接口隔離原則(Interface Segregation Principle)
下降類之間的耦合度,不依賴沒必要要的接口。

五、迪米特法則,又稱最少知道原則(Demeter Principle)
模塊之間相互獨立,對本身依賴的類須要知道的信息越少越好。

六、合成複用原則(Composite Reuse Principle)
儘可能使用合成/聚合的方式,而不是使用繼承。

具體的解讀,今天無法在一篇推送中展開詳述,並且這是個須要不斷體會和實踐的事情。首先你能夠找些相關書籍讀一讀。設計模式有一本經典書籍:《Design Patterns: Elements of Reusable Object-Oriented Software》(《設計模式:可複用面向對象軟件的基礎》)。此書又被稱做「GoF」(Gang of Four,四人組),四位業內大牛總結出了 23 種設計模式。

然而,我強烈不推薦新手去看這本書,由於你極可能看不懂。我推薦的是一本叫作《Head first 設計模式》的書,能夠算做上面那本的白話入門版,對於新手來講友好許多,或許幫助更大。

開發者對於設計模式的理解大體存在這樣幾個階段:一開始只關注語法和庫,不懂設計模式,寫代碼無章法;後來瞭解了設計模式以後,開始嘗試套用設計模式,懂得重構代碼,但有時不免教條化或陷入過分設計的誤區;等到開發經驗豐富以後,再也不拘泥於所謂的「模式」,自己寫出的代碼就已經契合設計的原則。

書上的設計模式是一成不變的,不可能涵蓋每一種開發場景,而軟件技術自己也不斷髮展,不少模式已經被新的語言特性所實現。所以也有不少人對於設計模式的價值存在質疑。個人見解是,若是你處在新手階段,學習設計模式是很好的提高方式,也能夠開拓你的編程思惟。而當你已經走上進階之路以後,更多的應是關注模式背後的原則,寫出更合理的代碼,而並不是爲了模式而模式。

固然這一切,仍是都離不開足夠的代碼量。每一個程序員都是一行行代碼堆出來。

順便在此給你們推薦一個Java方面的交流學習羣:957734884,裏面會分享一些高級面試題,還有資深架構師錄製的視頻錄像:有Spring,MyBatis,Netty源碼分析,高併發、高性能、分佈式、微服務架構的原理,JVM性能優化這些成爲架構師必備的知識體系,主要針對Java開發人員提高本身,突破瓶頸,相信你來學習,會有提高和收穫。在這個羣裏會有你須要的內容 朋友們請抓緊時間加入進來吧

相關文章
相關標籤/搜索