天天看点

JavaScript与设计模式

  • js没有传统语言中的类式继承,通过原型委托方式实现对象间的继承
  • 面向对象三大特性:抽象、继承、多态

1.1 动态语言和鸭子类型

  • 静态类型语言在编译时便已确定变量的类型,而动态类型语言的变量类型要到程序运行的时候,待变量被赋予某个值之后,才会具有某种类型。

鸭子类型

“如果它走起路来像鸭子,叫起来也是鸭子,那么它就是鸭子。”

  1. 只关注对象行为,不关注对象本身。
  2. 故动态语言不必借助超类型帮助,实现面向接口编程

1.2 多态

what:将“做什么”和“谁去做以及怎么去做”分离开

why:给予了我们扩展程序的能力,程序看起来是可生长的,也符合开放-封闭原则。

How:即将不变的事物和可能改变的分离开。

example 1:使动物叫

在例子中,不变的部分是动物都会发出叫的动作,会变的是,动物的叫声不同。故程序可以分为两个部分。

function makeSound(animal){  
 animal.sound && animal.sound()  
}  
​  
// 改变的部分  
var Duck = function (){}  
Duck.prototype.sound = function (){  
 console.log('gagaga')  
}  
var Dog = function(){}  
Dog.prototype.sound = function(){  
 console.log('wangwangwang')  
}
           

// 不变的部分

上文谈到的多态实质上指的是对象的多态性。

Martin Fowler 在《重构:改善既有代码的设计》里写到:

多态的最根本好处在于,你不必再向对象询问“你是什么类型”而后根据得到的答案调用对象的某个行为——你只管调用该行为就是了,其他的一切多态机制都会为你安排妥当。

  1. JavaScript 的变量类型在运行期是可变的。一个 JavaScript 对象,既可以表示 Duck 类型的对象,又可以表示 Chicken 类型的对象,这意味着 JavaScript 对象的多态性是与生俱来的。
  2. 多态最根本的作用就是通过把过程化的条件分支语句转化为对象的多态性,从而消除这些条件分支语句。

example 2:调用地图Api

在本例子,会改变的是Api提供商,不变的是进行地图渲染的动作

//使用不同地图api进行渲染  
​  
//不变的是渲染行为  
var render = function(map){  
 if(map.show instanceof Function){  
 map.show()  
 }  
}  
//变的是 api提供者  
var gooleMap = {  
 show:function(){  
 console.log('gooleMap进行渲染')  
 }  
}  
​  
var baiduMap={  
 show:function(){  
 console.log('baiduMap进行渲染')  
 }  
}
           

设计模型与多态

  • 绝大部分设计模式的实现都离不开多态性的思想
  • 在JavaScript中函数是一等对象,

1.3 封装

封装的目的是将信息隐藏。一般而言,我们讨论的封装是封装数据和封装实现。这一节将讨论更广义的封装,不仅包括封装数据和封装实现,还包括封装类型和封装变化。

1.3.1 封装数据

  • 许多对象系统中,封装数据由语法解析实现,例如private、public等
  • js依靠变量的作用域实现封装特性,且只能模拟public和private

可使用let和函数来创建作用域

1.3.2 封装实现

从封装实现细节来讲,封装使得对象内部的变化对其他对象而言是透明的,也就是不可见的。

1.3.3 封装类型

封装类型是静态类型语言中一种重要的封装方式。一般而言,封装类型是通过抽象类和接口来进行的。把对象的真正类型隐藏在抽象类或者接口之后

在Javascript中,没有对抽象类和接口的支持,也没有能力进行类型封装。

1.3.4 封装变化

《设计模式》一书曾提到如下文字:

“考虑你的设计中哪些地方可能变化,这种方式与关注会导致重新设计的原因相反。它不是考虑什么时候会迫使你的设计改变,而是考虑你怎样才能够在不重新设计的情况下进行改变。这里的关键在于封装发生变化的概念,这是许多设计模式的主题。”

设计模式划分为创建型模式、结构性模式、行为型模式

  1. 创建型模式: 创建对象是一种抽象行为,即创建什么对象是可以变化的。即封装创建对象的变化
  2. 结构性模式: 封装对象间的组合关系
  3. 行为型模式:封装对象的行为变化

在系统演变中,只需替换可变的部分,因为已经封装好,故替换起来相对容易。最大程度地保证程序地稳定性和可扩展性

继续阅读