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. iOS 导航栏不可点击

    self.navigationController.navigationBar.userInteractionEnabled = NO;

  2. IOS 上线问题

    info.plist 是否支持后台位置 音频 Info.plist中添加UIBackgroundModes键值,它包含一个或多个string的值,包括 audio:在后台提供声音播放功能,包括音频流和 ...

  3. NodeMCU之旅(四):实现Web配置页面

    引言 利用Web页面做配置可以轻松适应用户的多种设备,如Android, IOS等.本文将介绍如何在NodeMCU中实现配置页面. 接线图请参考NodeMCU之旅(三):响应配置按钮. 配置页面后端 ...

  4. window 2008+apache2.4.4+php5.5+mysql-5.6.12+phpmyadmin4.0.4.1安装过程(参考他人文章基础上加上自己遇到的问题)

    一.window server2008的安装 1.我用U盘安装的,先用UltraISO把server2008刻录到U盘中,过程我搜了一下,帖个地址: http://wenku.baidu.com/vi ...

  5. PHP 绘图技术

    1.图片格式:目前网站开发常见的图片格式有gif,jpg/jpeg,png ..... 区别: gif 图片压缩率高,但是只能显示256色,可能造成颜色的丢失,可以显示动画 jpg/jpeg 图片压缩 ...

  6. HDU2066:一个人的旅行(Dijkstra)

    Problem Description 虽然草儿是个路痴(就是在杭电待了一年多,居然还会在校园里迷路的人,汗~),但是草儿仍然很喜欢旅行,因为在旅途中 会遇见很多人(白马王子,^0^),很多事,还能丰 ...

  7. js原生设计模式——7原型模式之真正的原型模式——对象复制封装

    <!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8&qu ...

  8. 天兔(Lepus)监控操作系统(OS)安装配置

    监控和被监控端都要安装和配置snmp: [root@HE1bin]# yum install net-snmp* [root@HE1bin]# vi /etc/snmp/snmpd.conf 41行将 ...

  9. win7配置自己的IIS服务器亲自做的图文很详细

    跟人网站爱好初学者必看的win7系统配置自己的IIS,可以在你自己的电脑上配置网站服务器发不到网上,下面就跟着我的步骤一起做吧100%成功. 步骤/方法     点击开始-------控制面板这个就是 ...

  10. JSP page指令

    JSP page指令: JSP文件: <%@ page language="java"%> <%@ page import="java.util.*&q ...