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

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

  • 代碼中有不少類似的重複代碼
  • 代碼中有大量的 if,以致於有很長的縮進
  • 單個代碼寫得很長,別人很難看懂,過陣子可能本身都看不懂
  • 總會有沒有考慮到的狀況致使 bug
  • 修復一個 bug 又會產生新的 bug
  • 單個功能能夠實現,但多個功能組合在一塊兒就理不清
  • 若是需求發生變更,代碼修改起來很麻煩
  • 有多種實現方式時不知道該用哪種
  • 很難和其餘人協做開發

上述的問題你是否是有過相似困擾?解決的辦法其實也簡單,就是堅持「 多寫 」和「 多讀 」:編程

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

除了這兩個「笨辦法」外,還有樣東西,對於處在這個階段的你或許有很大啓發,這就是:設計模式

設計模式

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

舉幾個常見的設計模式例子:學習

單例模式網站

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

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

代碼演示代理

# 單例類
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)

輸出code

True
2

以前咱們的文章《Crossin:Python單例模式(Singleton)的N種實現》有專門討論過 Python 中的單例模式實現。

工廠模式

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

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

代碼演示

# 筆刷工廠,具體類代碼略
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 設計模式 》的書,能夠算做上面那本的白話入門版,對於新手來講友好許多,或許幫助更大。

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

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

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

════

其餘文章及回答:

學編程:如何自學Python | 新手引導 | 一圖學Python

開發案例:智能防擋彈幕 | 紅包提醒 | 流浪地球

歡迎搜索及關注: Crossin的編程教室

相關文章
相關標籤/搜索