使用修饰器实现Mixin模式

在修饰器的基础上,可以实现Mixin模式。所谓Mixin模式,就是对象继承的一种替代方案,中文译为“混入”(mix in),意为在一个对象之中混入另外一个对象的方法。

请看下面的例子。

  1. const Foo = {
  2. foo() { console.log('foo') }
  3. };
  4. class MyClass {}
  5. Object.assign(MyClass.prototype, Foo);
  6. let obj = new MyClass();
  7. obj.foo() // 'foo'

上面代码之中,对象Foo有一个foo方法,通过Object.assign方法,可以将foo方法“混入”MyClass类,导致MyClass的实例obj对象都具有foo方法。这就是“混入”模式的一个简单实现。

下面,我们部署一个通用脚本mixins.js,将 Mixin 写成一个修饰器。

  1. export function mixins(...list) {
  2. return function (target) {
  3. Object.assign(target.prototype, ...list);
  4. };
  5. }

然后,就可以使用上面这个修饰器,为类“混入”各种方法。

  1. import { mixins } from './mixins';
  2. const Foo = {
  3. foo() { console.log('foo') }
  4. };
  5. @mixins(Foo)
  6. class MyClass {}
  7. let obj = new MyClass();
  8. obj.foo() // "foo"

通过mixins这个修饰器,实现了在MyClass类上面“混入”Foo对象的foo方法。

不过,上面的方法会改写MyClass类的prototype对象,如果不喜欢这一点,也可以通过类的继承实现 Mixin。

  1. class MyClass extends MyBaseClass {
  2. /* ... */
  3. }

上面代码中,ES6 MyClass继承了MyBaseClass。如果我们想在MyClass里面“混入”一个foo方法,一个办法是在MyClassMyBaseClass之间插入一个混入类,这个类具有foo方法,并且继承了MyBaseClass的所有方法,然后MyClass再继承这个类。

  1. let MyMixin = (superclass) => class extends superclass {
  2. foo() {
  3. console.log('foo from MyMixin');
  4. }
  5. };

上面代码中,MyMixin是一个混入类生成器,接受superclass作为参数,然后返回一个继承superclass的子类,该子类包含一个foo方法。

接着,目标类再去继承这个混入类,就达到了“混入”foo方法的目的。

  1. class MyClass extends MyMixin(MyBaseClass) {
  2. /* ... */
  3. }
  4. let c = new MyClass();
  5. c.foo(); // "foo from MyMixin"

如果需要“混入”多个方法,就生成多个混入类。

  1. class MyClass extends Mixin1(Mixin2(MyBaseClass)) {
  2. /* ... */
  3. }

这种写法的一个好处,是可以调用super,因此可以避免在“混入”过程中覆盖父类的同名方法。

  1. let Mixin1 = (superclass) => class extends superclass {
  2. foo() {
  3. console.log('foo from Mixin1');
  4. if (super.foo) super.foo();
  5. }
  6. };
  7. let Mixin2 = (superclass) => class extends superclass {
  8. foo() {
  9. console.log('foo from Mixin2');
  10. if (super.foo) super.foo();
  11. }
  12. };
  13. class S {
  14. foo() {
  15. console.log('foo from S');
  16. }
  17. }
  18. class C extends Mixin1(Mixin2(S)) {
  19. foo() {
  20. console.log('foo from C');
  21. super.foo();
  22. }
  23. }

上面代码中,每一次混入发生时,都调用了父类的super.foo方法,导致父类的同名方法没有被覆盖,行为被保留了下来。

  1. new C().foo()
  2. // foo from C
  3. // foo from Mixin1
  4. // foo from Mixin2
  5. // foo from S

es6 使用修饰器实现Mixin模式相关推荐

  1. es6 Trait修饰器

    Trait修饰器 ES6 Trait 也是一种修饰器,效果与 Mixin 类似,但是提供更多功能,比如防止同名方法的冲突.排除混入某些方法.为混入的方法起别名等等. 下面采用traits-decora ...

  2. es6 使用修饰器实现自动发布事件

    使用修饰器实现自动发布事件 我们可以使用修饰器,使得对象的方法被调用时,自动发出一个事件. const postal = require("postal/lib/postal.lodash& ...

  3. es6 为什么修饰器不能用于函数

    为什么修饰器不能用于函数 ES6 修饰器只能用于类和类的方法,不能用于函数,因为存在函数提升. var counter = 0; var add = function () { counter++; ...

  4. ES6 (二十二)Class 的继承、extends关键字、super 关键字(函数调用(constructor)、对象(父类原型对象))、原型对象(原型链)、Mixin 模式

    ES6 (二十二)Class 的继承.extends关键字.super 关键字(函数调用(constructor).对象(父类原型对象)).原型对象(原型链).Mixin 模式 文章目录 ES6 (二 ...

  5. ES6里的修饰器Decorator

    修饰器(Decorator)是一个函数,用来修改类的行为. 一.概述 ES6 引入了这项功能,目前 Babel 转码器已经支持Decorator 首先,安装babel-core和babel-plugi ...

  6. ES6新特性之修饰器

    修饰器(Decorator) 修饰器(Decorator)是一个函数, 用来修改类的行为. ES2017 引入了这项功能, 目前 Babel 转码器己经支持. 使用: <script>@T ...

  7. python模式选择符,Python设计模式之修饰器模式

    无论何时我们想对一个对象添加额外的功能,都有下面这些不同的可选方法. 如果合理,可以直接将功能添加到对象所属的类(例如:添加一个新方法) 使用组合 使用继承 与继承相比,通常应该优先选择组合,因为继承 ...

  8. es6 Babel 转码器对修饰器的支持

    Babel 转码器对修饰器的支持 目前,Babel 转码器已经支持 Decorator. 首先,安装babel-core和babel-plugin-transform-decorators.由于后者包 ...

  9. es6 方法的修饰器

    方法的修饰器 修饰器不仅可以修饰类,还可以修饰类的属性. class Person { @readonly name() { return `${this.first} ${this.last}` } ...

最新文章

  1. 二叉树学习笔记之树的旋转
  2. 我问占小狼到底什么是面向对象编程?他转头就走。
  3. 算法--------打家劫舍(动态规划,Java版本)
  4. 如何在NEO共识节点间分配任务
  5. 【Android 应用开发】Android之Bluetooth编程
  6. 中国数据中心市场时评—简析全国数据中心布局情况
  7. 转载:tensorflow保存训练后的模型
  8. 1、eclipse 使用git提交项目至github进行项目托管
  9. Matlab - 文件目录路径操作
  10. SQLConnect
  11. 【原】GitHub使用教程
  12. 【ModBus】基础使用:【01】MThings国产调试工具
  13. marlab中主成分得分怎么求_R语言 | 主成分分析(PCA)代码+讲解
  14. php AES加解密
  15. 最好的开源网络入侵检测工具(网址及版本已验证并更新)
  16. 网站1周内自动登录功能实现
  17. 软考 第十一章 软件知识产权基础知识
  18. HDOJ 4747 Mex
  19. 从 DP 到 DDP 到 apex
  20. 用Carbide C++ UI Designer做UI的爽与不爽

热门文章

  1. NAT原理?代理服务器原理?
  2. Network | DNS
  3. 美国人教你这样用Google,你真的会变特工!
  4. xfce 双击窗口标题栏无法最大化解决办法
  5. 视频数据:骨骼数据采集(Skeleton Data)
  6. C---队列,栈的实现
  7. HDU 3662 3D Convex Hull(三维凸包面的个数)
  8. AWS手动创建VPC
  9. 为什么使用 Redis及其产品定位
  10. 第六章—条件语句和循环