Mixin(织入)模式并不是GOF的《设计模式》归纳中的一种,但是在各种语言以及框架都会发现该模式(或者思想)的一些应用。简单来说,Mixin是带有全部实现或者部分实现的接口,其主要作用是更好的代码复用。本文将介绍Mixin的应用场景,以及关于继承、组合、多继承、接口的一些思考。
 

相关概念:

  前面提到,Mixin是有部分或者全部实现的接口,其主要作用是代码复用,需要理解这个简单的描述,需要先理清一些概念。

继承与组合:

  继承是面向对象的三大特征(封装、继承、多态),如果类A继承自类B,那么我们称A为子类(派生类),称B为父类(基类)。什么时候类A才能继承类B呢,可以说A是B的一种特殊化,英语来说就是A is a B,或者A is a kind of B。比如狗(dog)和动物(Animal)这两个抽象,dog is animal,这个是成立的,所以dog可以继承自animal。
  而组合代表的是其中一个类的对象是另一个类的对象的组成组合,英语来说,“has a”,比如人(People)这个类有一个属性addr是一个地址类(Address)的实例,就是说每个人都有一个地址。
  不管是继承还是组合,都起到了代码复用的作用,但又各有优缺点。上面继承和组合的例子都很明显,但有些情况就不那么容易区分两类事物是继承还是组合的关系了,或者说,两个类之间既可以用继承,又可以用组合,比如设计模式中的adapter模式,既可以类适配,又可以组合适配(对象适配)。
 

多继承与接口:

  在使用编程语言抽象事物之间的继承关系的时候,需要考虑对多继承的实现。所谓多继承就是说一个类有多个基类,举个简单的例子,dog是animal,同时dog又是runnable(可以跑动的对象)。多继承对于人类的思维来说是比较正常直观的,但是对于计算机编程语言,都会遇到一个绕不过去的问题,那就是菱形继承(diamond problem),下面这个图形象展示了什么时菱形继承:
  
  从上图可以看到,类B、类C都继承了类A,类D同时继承了类B和类C,在继承关系上就形成了“菱形”--类D有两条路径到达类A。菱形问题带来什么问题呢,如果类A定义了某个方法foo,而且B和C都没有重写该方法,那么B和C都会有某种机制找到foo,那么对于D的实例在调用foo方法的时候,是调用到B中指向的foo方法还是C中指向的foo方法呢?
  菱形继承的问题会影响到语言的设计,一些编程语言支持多继承,如C++、python等等;另外一些则不支持多继承,如Java,ruby等。对于支持多继承的语言,为了解决菱形继承的问题,一般都会使用特定的方法,比如C++中的虚继承,python中的新式类的MRO。而对于不支持多继承的语言,一般使用某种接口(或者约定、协议)来实现多继承的功能,如Java中的interface,ruby中的include module。
 

duck typing:

  一个事物是不是鸭子(duck),如果它走起来像一只鸭子、叫起来也像一只鸭子,即从表现来看像一只鸭子,那么我们就认为它是一只鸭子。把这种思想应用到编程中,就是duck typing,简而言之,一个约定要求必须实现某些功能,而某个类实现了这个功能,就可以把这个类当做约定的具体实现来使用。duck typing的思想在编程语言中的使用非常广泛,如Java中的Interface,Python中的各种protocol,ruby中的include module。
  上面提到协议(泛指接口、预定、duck typing,下同)可以用来实现多继承的功能,在以下情况特别合适:“基类”代表的其实是一种能力或者承诺。比如前面dog同时继承animal和runnale,但跑(run)就是一种能力的体现,这个时候就可以把runable作为一个协议,dog是可以跑的,所以应该实现run方法,也就遵循了这个协议,那么dog就是一个runable了。从例子可以看出,如果一个所谓的“基类”事实上代表了某种能力(it can,xxxable)的时候,使用协议比多继承是更佳合理的选择。
 

Mixin:

  在前面说清楚了各个概念之后,我们来看看Mixin到表代表了什么,不过再次回顾上面一段提到的java interface和python protocol,这二者本身是没有任何实现的,都是需要使用者来实现相应的方法。Mixin本身也是一种能力的承诺,但Mixin不同的不同之处在于Mixin是有部分或者全部实现的,在Mixin中的实现有利于代码复用。如果是部分实现,那么就是在Mixin中实现整个流程,而实现Mixin约定的类提供关键的、该类特有的方法,这有点类似模板模式,也是依赖倒置原则的体现。
  不同的语言或者框架中,对Mixin模式有不同的实现形式,python中,除了protocol,也可以用多继承的形式来实现Mixin,为了区分普通的多继承,Mixin类的类名一般都会带上后缀:“Mixin”,比如python lib里面的两个Mixin类:UserDict.DictMixin和SocketServer.ForkingMixIn。DictMixin类包括部分实现,使用者只要实现几个核心的函数接口就行了。
  Mixin defining all dictionary methods for classes that already have a minimum dictionary interface including getitem, setitem, delitem,and keys. 
  而python中的SocketServer.ForkingMixIn有全部的实现,所以使用者无需特殊处理,就拥有了fork带来的好处,例如
  

 class ForkingUDPServer(ForkingMixIn, UDPServer): pass
class ForkingTCPServer(ForkingMixIn, TCPServer): pass
  在python的一些框架中,也有Mixin的身影,如tornado。
  在ruby中,并不直接使用Mixin这个单词,而是使用在类的声明中include 一个module的办法,如下面的代码(来自wiki):
 class Student
include Comparable # The class Student inherits Comparable module using include keyword
attr_accessor :name, :score def initialize(name, score)
@name = name
@score = score
end # Including the Comparison module, requires the implementing class to define the <=> comparison operator
# Here's the comparison operator. We compare 2 student instances based on their scores. def <=>(other)
@score <=> other.score
end end

  首先,include的module叫Comparable (Java中也有一个同名的接口),即可比较的对象,按照之前对协议、约定的讲解,是非常适合使用Mixin模式的。其次,ruby中Comparable这个module也是部分实现,需要具体的类实现<=>方法。


总结:

  Mixin是一种思想,用部分实现的接口来实现代码复用。可以用来解决多继承的问题,又可以用来扩展功能。Mixin在不同的编程语言中又不同的使用形式或者命名,但其本质都是一样的。
 
references:
  
 

Mixin模式:带实现的协议的更多相关文章

  1. 什么是Mixin模式:带实现的协议

    Mixin(织入)模式并不是GOF的<设计模式>归纳中的一种,但是在各种语言以及框架都会发现该模式(或者思想)的一些应用.简单来说,Mixin是带有全部实现或者部分实现的接口,其主要作用是 ...

  2. PythonI/O进阶学习笔记_3.2面向对象编程_python的继承(多继承/super/MRO/抽象基类/mixin模式)

    前言: 本篇相关内容分为3篇多态.继承.封装,这篇为第二篇 继承. 本篇内容围绕 python基础教程这段: 在面向对象编程中,术语对象大致意味着一系列数据(属性)以及一套访问和操作这些数据的方法.使 ...

  3. 设计模式之Mixin模式

    介绍 mixin模式就是一些提供能够被一个或者一组子类简单继承功能的类,意在重用其功能.在面向对象的语言中,我们会通过接口继承的方式来实现功能的复用.但是在javascript中,我们没办法通过接口继 ...

  4. mixin模式特点

    mixin模式特点: 1.单一功能, 2.不和基类关联,可以和任意基类组合,基类可以不和mixin关联就可以初始化成功 3.不使用 super() 用法

  5. 搭建高可用的redis集群,避免standalone模式带给你的苦难

    现在项目上用redis的话,很少说不用集群的情况,毕竟如果生产上只有一台redis会有极大的风险,比如机器挂掉,或者内存爆掉,就比如我们生产环境 曾今也遭遇到这种情况,导致redis内存不够挂掉的情况 ...

  6. Mixin模式

    Mixin是JavaScript中用的最普遍的模式,几乎所有流行类库都会有Mixin的实现. Mixin是掺合,混合,糅合的意思,即可以就任意一个对象的全部或部分属性拷贝到另一个对象上. 从提供的接口 ...

  7. 【javascript】javascript设计模式mixin模式

    概述: Mixin是JavaScript中用的最普遍的模式,几乎所有流行类库都会有Mixin的实现.任意一个对象的全部或部分属性拷贝到另一个对象上. 一 .混合对象 二 .混合类

  8. Android基础相关面试问题-activity面试问题(生命周期,任务栈,启动模式,跳转协议,启动流程)

    关于Android的一些面试题在15年就已经开了这个专栏了,但是一直木有坚持收集,而每次面对想要跳槽时大脑一片空白,也有些恐惧,因为毕境面试都是纯技术的沟通,要想让公司对你的技术能有所认可会全方位的进 ...

  9. 前端框架中 “类mixin” 模式的思考

    "类 mixin" 指的是 Vue 中的 mixin,Regular 中的 implement 使用 Mixin 的目的 首先我们需要知道为什么会有 mixin 的存在? 为了扩展 ...

随机推荐

  1. c++ split()实现

    在c++中,没有java与python中定义的split()功能的函数,于是自己实现之. 情况1,适用范围,分隔符为字符.思路,记录分隔符的位置,判断需要截取的字符串的下标范围. vector< ...

  2. 谈谈字符集编码及gb2312、utf-8编码原理

    一.基础中的基础比特位即bit,是计算机最小的存储单位.以0或1来表示比特位的值.Byte是字节数,bit是位数,在计算机中每八位为一字节,也就是1Byte=8bit:Byte和bit都翻译成比特,俗 ...

  3. angularjs---服务(service / factory / provider)

    初angularJs时  常写一些不够优雅的代码  !我总结了一下看看各位有没有中枪的!-----( 这里只针对服务service及其相关! ) 以下做法不太优雅 兄弟controller 之间的相同 ...

  4. js原生之函数

    1.函数作为参数传给其他函数:    data.sort(function(a,b){return a-b})    //关于数组的sort函数,其回调函数返回负值,a在b之前    //正值,b在a ...

  5. flex 事件注册和鼠标拖动

    flex 事件注册和鼠标拖动 <?xml version="1.0" encoding="utf-8"?> <s:Application xm ...

  6. 给Pomelo的聊天室添加time的RPC调用

    为了练手,给聊天应用增加一个rpc调用和一个time类型的服务器,在servers/time/remote/timeRemote.js中,添加如下代码: module.exports.getCurre ...

  7. easyUI tootip组件使用

    easyUI tootip组件使用: <!DOCTYPE html> <html lang="en"> <head> <meta char ...

  8. jQuery获取URL中所带参数的办法

    可以使用正则表达式进行结果的拆分: http://www.cnblogs.com/babycool/p/3169058.html 可以直接进行所需内容的split: http://blog.scien ...

  9. Bootstrap入门(七)组件1:字体图标

    Bootstrap入门(七)组件1:字体图标   包括200个来自 Glyphicon Halflings 的字体图标,允许 Bootstrap 免费使用. 部分可用图标截图: 所有图标都需要一个基类 ...

  10. Kafka 0.8源码分析—ZookeeperConsumerConnector

    1.HighLevelApi High Level Api是多线程的应用程序,以Topic的Partition数量为中心.消费的规则如下: 一个partition只能被同一个ConsumersGrou ...