設計模式與面向對象


一、設計模式

  設計模式:對軟件設計中普遍存在(反復出現)的各種問題,所提出的解決方案。

  每一個設計模式系統地命名、解釋和評價了面向對象系統中一個重要的和重復出現的設計

  設計模式的創始人,一般稱為“四人幫”(Gang of Four, GoF):Erich Gamma,Richard Helm,Ralph Johnson,John Vlissides......他們編寫一套書來介紹23種設計模式:《設計模式:可復用面向對象軟件的基礎》。

二、面向對象回顧

  設計模式是用來設計面向對象系統中的設計。不解決面向過程的問題。

1、面向對象的三大特性

  封裝:把數據和函數封裝到一個類里,體現類內和類外。

  繼承:由於有了封裝,需要通過繼承在類之間復用代碼。

  多態:python本身是一門多態語言,因此不需去處理多態的問題。Java中則會區分虛類和普通類。

  因此這三個特性是一個遞進的關系。

2、接口

  接口:若干抽象方法的集合。

  作用:限制實現接口類必須按照接口給定的調用方式實現這些方法;對高層模塊隱藏了類的內部實現

# 方法一:繼承
# 存在的問題是:如果不調用pay方法並不會報錯
class Payment:
    def pay(self, money):
        raise NotImplementedError

class Alipay(Payment):
    pass

class WechatPay(Payment):
    pass

p = Alipay()
p.pay(100)


# 方法二:抽象類
# 約束子類必須實現抽象類:TypeError: Can't instantiate abstract class Alipay with abstract methods pay
from abc import ABCMeta, abstractmethod

class Payment(metaclass=ABCMeta):
    # abstract class
    @abstractmethod
    def pay(self, money):   # 抽象方法
        pass

class Alipay(Payment):
    def pay(self, money):   # 實現Payment接口
        print('支付寶支付%d元' % money)

class WechatPay(Payment):
    def pay(self, money):   # 實現Payment接口
        print("微信支付%d元" % money)

p = Alipay()
p.pay(100)

  不用去查看具體實現,只要去查看接口(抽象類)的結構和注釋,就可以了解需要傳遞的參數和pay方法的使用。

  在寫底層模塊或者開源框架時需要大量應用設計模式,優化封裝,讓程序員在學習和使用時非常方便。

三、面向對象設計SOLID原則

  不管是面向對象設計還是各個設計模式都需要遵循這五大原則。

  • 開放封閉原則:一個軟件實體如類、模塊和函數應該對擴展開放,對修改關閉。即軟件實體應盡量在不修改原有代碼的情況下進行擴展
  • 里氏替換原則:所有引用父類的地方必須能透明地使用其子類的對象。(子類是特殊的父類,子類繼承父類時同樣方法的表現一致)
    # 子類和父類的show_name內部實現和邏輯可能不同,但是參數和返回值是相同的
    class User:
        def show_name(self):
            pass
    
    class VIPUser(User):
        def show_name(self):
            pass
    
    def show_user(u):  # u可以是普通用戶或VIP
        res = u.show_name()
  • 依賴倒置原則:高層模塊不應該依賴低層模塊,二者都應該依賴其抽象;抽象不應該依賴細節;細節應該依賴抽象。換言之,要針對接口編程,而不是針對實現編程。
    from abc import ABCMeta, abstractmethod
    
    class Payment(metaclass=ABCMeta):  # 抽象
        # abstract class
        @abstractmethod
        def pay(self, money):   # 抽象方法
            pass
    
    class Alipay(Payment):      # 細節
        def pay(self, money):   # 實現Payment接口
            print('支付寶支付%d元' % money)
    
    class WechatPay(Payment):   # 細節
        def pay(self, money):   # 實現Payment接口
            print("微信支付%d元" % money)
  • 接口隔離原則:使用多個專門的接口,而不使用單一的總接口,即客戶端不應該依賴那些它不需要的接口。
    from abc import ABCMeta, abstractmethod
    
    # (一)單一總接口的情況
    # 子類必須實現所有抽象方法,但其實很多方法是子類不需要的
    class Animal(metaclass=ABCMeta):
        @abstractmethod
        def walk(self):
            pass
    
        @abstractmethod
        def swim(self):
            pass
    
        @abstractmethod
        def fly(self):
            pass
    
    class Tiger(Animal): # Class Tiger must implement all abstract methods
        def walk(self):
            print("老虎走路")
    
    # (二)多個接口隔離情況
    class LandAnimal(metaclass=ABCMeta):
        @abstractmethod
        def walk(self):
            pass
    
    class WaterAnimal(metaclass=ABCMeta):
        @abstractmethod
        def swim(self):
            pass
    
    class SkyAnimal(metaclass=ABCMeta):
        @abstractmethod
        def fly(self):
            pass
    
    class Tiger(LandAnimal):
        def walk(self):
            print("老虎走路")
    
    class Frag(LandAnimal,WaterAnimal):  # 青蛙多繼承
        pass
  • 單一職責原則:不要存在多於一個導致類變更的原因。通俗的說,即一個類只負責一項職責

四、設計模式分類

1、創建型模式(5種)

  主要聚焦怎么去創建對象。目的是為了隱藏底層模塊的邏輯。

  工廠方法模式、抽象工廠模式、創建者模式、原型模式、單例模式。

  創建型模式

2、結構型模式(7種)

  主要關注在幾個類之間怎么組合協同工作在一起。

  適配器模式、橋模式、組合模式、裝飾模式、外觀模式、享元模式、代理模式。

  結構型模式

3、行為型模式(11種)

  主要關注方法和行為的完成。

  解釋器模式、責任鏈模式、命令模式、迭代器模式、中介者模式、備忘錄模式、觀察者模式、狀態模式、策略模式、訪問者模式、模板方法模式。

  行為型模式

五、設計模式總結

  python這門語言是一個動態語言,對參數、父類子類等限制不嚴格。對設計模式並不強求,不是完全契合,而java則是完全與設計模式契合。但是了解一些設計模式對寫出優秀代碼還是非常有幫助的。

  在寫大型項目時,尤其是底層代碼、開源框架等時,設計模式的優勢將更加突出。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM