1. 什麼是 Mixin 設計模式#
mixin
設計模式可以看作是多繼承的一種。那么首先,咱們談談為什麼會出現多繼承這種語法。
汽車和飛機他們都同屬於交通工具,但飛機可以飛行,汽車無法做到,所以,飛行這個行為不能寫到交通工具這個類中,如果每一個交通工具各自實現自己的行駛方法,就違背了代碼儘可能重用的原則(如果交通工具種類越來越多,就會造成大量代碼冗餘)。
所以,我們要表示飛行這個行為,就需要進行多繼承。但這樣,我們就違背了繼承關係必須是is-a
原則。
在 java 中,雖然沒有多繼承,但我們可以通過interface
來實現多繼承。
在 python 中,沒有interface
這一語法,但它本身是支持多繼承的。
在使用多繼承的時候,很容易就會設計不當,導致繼承鏈混亂,影響mro
查找,所以,在編程的時候我們的原則就是,能使用其他方法代替多繼承就儘量不適用多繼承。
這個時候Mixin
設計模式就應運而生,Mixin
直譯理解就是混入、補充的意思,它是多繼承的一種。在多繼承中,查找順序是按mro
繼承鏈中的順序進行的。
2. Mixin 設計模式實例#
class Vehicle:
pass
class PlaneMixin:
def fly(self):
print("Flying")
class Airplane(Vehicle, PlaneMixin):
pass
可以看到,上述代碼中,Airplane
類實現了多繼承,在繼承鏈上,它繼承了Vehicle
類和PlaneMixin
類,這裡我們遵循Mixin
設計模式的要求,在後面添加上後綴Mixin
增強代碼的可讀性。
上述代碼可以這麼理解,Airplane
只是個Vehicle
類,而不是Plane
類,而Mixin
後綴,它告訴其他讀者,這個類是作為功能添加到子類中的,並不是作為父類,它的作用等同於 Java 中的interface
。
這樣一來,我們不需要複雜而龐大的繼承鏈,只要選擇組合不同的類的功能,就可以快速構造出所需的子類。
3. 使用 Mixin 設計模式的原則#
在使用Mixin
設計模式實現多重繼承的時候要特別注意下列幾點原則:
- 首先,Mixin 類必須表示某一種功能,而不是某一個物體,這點跟 java 中的
Runnable
和Callable
是一樣的。 - 其次,它表示的責任必須單一,如果有多個功能,我們應該去實現多個
Mixin
類。 - 接下來,Mixin 類不依賴於子類的實現,且屬於抽象類,本身不能實例化,也不能繼承 Mixin 以外的類。
- 最後,子類即使沒有繼承 Mixin 類,也必須照常工作,只是部分功能缺少無法使用。
Java 的接口,只提供了 “規格” 的多重繼承。Mixin 類則同時提供了 “規格” 和 “實現” 的多重繼承,使用上相比接口會更加簡單。
4. 補充#
在其他框架或者語言中,也有類似的 Mixin 功能,如Ruby
,Django
,Vue
, React
等等。