鸭子模型???

最近在网上看到一个概念:“鸭子模型”,出于好奇搜一下然后就有了这篇水文,各位看一下图个乐呵就好了

背景

如果它走起来像鸭子,而且叫起来像鸭子,那么它就是鸭子
也就是说,我们只关注对象行为而不关注对象本身

推论

  • 凡是这样签名的方法:object.method(arg1, arg2, …)的方法,都可以采用method.apply(object, [arg1, arg2, …])进行调研。
  • array的某些方法(不会修改array状态)可以使用arguments以Array.prototype.method.apply(arguments,[arg1, arg2, …])的方式调用。
    前者是将array当作arguments(鸭子)
    后者是将argument当成array(鸭子)

eg:

1
2
3
4
5
6
7
8
9
10
console.log(Math.max.apply(Math, [3, 2, 1]));

var arr = [1, 2, 3];
Array.prototype.push.apply(arr, [4, 5, 6]);
console.log(arr);

(function () {
var arr = Array.prototype.slice.apply(arguments);
console.log(arr);
})(1, 2, 3);
  • 利用鸭子类型的思想,我们不必借助超类型的帮助,就能轻松地在动态类型语言中实现一个原则:“面向接口编程,而不是面向实现编程”。例如,一个对象若有push和pop方法,并且这些方法提供了正确的实现,它就可以被当作栈来使用。一个对象如果有length属性,也可以依照下标来存取属性(最好还要拥有slice和splice等方法),这个对象就可以被当作数组来使用。

  • 在静态类型语言中,要实现“面向接口编程”并不是一件容易的事情,往往要通过抽象类或者接口等将对象进行向上转型。当对象的真正类型被隐藏在它的超类型身后,这些对象才能在类型检查系统的“监视”之下互相被替换使用。只有当对象能够被互相替换使用,才能体现出对象多态性的价值。

  • 我们将伪数组转换为数组的方法也是鸭子类型:

1
2
var arr = Array.prototype.slice.apply({0:1,1:2,2:3,length:3});
console.log(Array.isArray(arr)); //true

鸭子类型和隐式接口有那么一点点类似,它扩大了多态的概念。

Ps:上面的内容都是我抄大佬的!
原文地址链接在这里Javascript:由 “鸭子类型” 得出来的推论,看完记得给大佬点个赞。
典故在这里:鸭子模式的由来

最近UML课程在学射击模式好像也谈到了,等我学会了再更一点吧~


今天看到了零一篇博客,正好可以用来例证我们最开始所说的“如果它走起来像鸭子并且叫声像鸭子那么它就是鸭子”的霸王理论。话不多说上代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
var duck = {    //鸭子
duckSinging:function(){
return "嘎";
}
};

var chicken = { //鸡
duckSinging:function(){
return "嘎";
}
}

var choir = []; //合唱团

var joinChoir = function(animal){ //加入合唱团的方法
if(animal && animal.duckSinging() === "嘎"){
choir.push(animal);
console.log("恭喜加入合唱团");
}
}

for(var i =0;i<999;i++){ //加入999只鸭子
joinChoir(duck);
}
joinChoir(chicken);

console.log(choir.length); //1000 现在凑齐了1000只可以嘎嘎叫的动物,不用管它是不是鸭子

说实话我还是改了一部分的,原博主的判断条件有点问题,我也给他评论了,暂时就这样吧