鸭子类型(duck typing)在程序设计中是动态类型的一种风格。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由"当前方法和属性的集合"决定。这个概念的名字来源于由詹姆斯·惠特科姆·莱利提出的鸭子测试,“鸭子测试”可以这样表述:
“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”
从问题开始:我们在利用继承来提供某个类的行为,会导致一些问题。
比如:
1.代码在多个子类中重复
2.运行时的行为不容易改变
3.很难知道所要实现的类的所有行为。
4.改变父类的时候会导致牵一发而动全身,对其他子类造成影响。
同时继承接口无法达到代码的复用,这个意味着:无论何时你需要修改某个行为,你必须得往下追踪并在每一个定义此行为的类中修改它,一不小心,会引发新的错误!
这儿引出了Head-First设计模式这本书中的一个设计原则:
找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。
如此,代码变化引起的不经意后果变少,系统变得更有弹性。
以下采用javascript实现鸭子类型(多态)
var duck = {
duckSinging: function(){
console.log( '嘎嘎嘎' );
}
};
var chicken = {
duckSinging: function(){
console.log( '嘎嘎嘎' );
}
};
var choir = []; // 合唱团
var joinChoir = function(animal) {
if (animal && typeof animal.duckSinging === 'functioin') {
choir.push(animal);
console.log('恭喜加入合唱团');
console.log('合唱团已有成员数量:' + choir.length);
}
};
joinChoir(duck); // 恭喜加入合唱团
joinChoir(chicken); // 恭喜加入合唱团
在鸭子类型中,关注点在于对象的行为,能作什么;而不是关注对象所属的类型。上述代码中chicken因为具有duckSinging的行为,以假乱真的加入了合唱团。
鸭子类型通常得益于"不"测试方法和函数中参数的类型,而是依赖文档、清晰的代码和测试来确保正确使用。
在常规类型中,我们能否在一个特定场景中使用某个对象取决于这个对象的类型,而在鸭子类型中,则取决于这个对象是否具有某种属性或者方法——即只要具备特定的属性或方法,能通过鸭子测试,就可以使用。
摘自javaScript设计模式与开发实践此书的应用例子:
假设我们要编写一个地图应用,现在有两家可选的地图 API 提供商供我们接入自己的应用。 目前我们选择的是谷歌地图,谷歌地图的 API 中提供了 show 方法,负责在页面上展示整个地图。 示例代码如下:
var googleMap = {
show: function() {
console.log('开始渲染谷歌地图')
}
}
var renderMap = {
googleMap.show();
}
renderMap(); // 开始渲染谷歌地图
后来因为某些原因,要把谷歌地图换成百度地图,或者其他地图,我们可以将程序中的相同部分抽象出来(地图部分),重写renderMap函数。
var googleMap = {
show: function(){
console.log( '开始渲染谷歌地图' );
}
};
var baiduMap = {
show: function(){
console.log( '开始渲染百度地图' );
}
};
var renderMap = function( map ){
if ( map.show instanceof Function ){
map.show();
}
};
renderMap( googleMap ); // 输出:开始渲染谷歌地图
renderMap( baiduMap ); // 输出:开始渲染百度地图
当我们向谷歌地图对象和百度地图对象分别发出“展示地 图”的消息时,会分别调用它们的 show 方法,就会产生各自不同的执行结果。对象的多态性提 示我们,“做什么”和“怎么去做”是可以分开的,即使以后增加了搜搜地图,renderMap 函数仍然不需要做任何改变。
var sosoMap = {
show: function(){
console.log( '开始渲染搜搜地图' );
}
};
renderMap( sosoMap ); // 输出:开始渲染搜搜地图
最后送上来自Head-First设计模式的一句话:
学习设计模式最好的方式是:”把模式装进脑子里,然后在你的设计和已有的应用中,寻找何处可以使用他们“.
公众号: 前端成长小册