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
等等。