You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
class Creator {
create(name) {
return new Animal(name)
}
}
class Animal {
constructor(name) {
this.name = name
}
}
var creator = new Creator()
var duck = creator.create('Duck')
console.log(duck.name) // Duck
var chicken = creator.create('Chicken')
console.log(chicken.name) // Chicken
小结:
构造函数和创建者分离,对new操作进行封装
符合开放封闭原则
单例模式
举一个书中登录框的例子,代码如下:
<!DOCTYPE html>
<html lang="en">
<body>
<button id="btn">登录</button>
</body>
<script>
class Login {
createLayout() {
var oDiv = document.createElement('div')
oDiv.innerHTML = '我是登录框'
document.body.appendChild(oDiv)
oDiv.style.display = 'none'
return oDiv
}
}
class Single {
getSingle(fn) {
var result;
return function() {
return result || (result = fn.apply(this, arguments))
}
}
}
var oBtn = document.getElementById('btn')
var single = new Single()
var login = new Login()
// 由于闭包,createLoginLayer对result的引用,所以当single.getSingle函数执行完之后,内存中并不会销毁result。
// 当第二次以后点击按钮,根据createLoginLayer函数的作用域链中已经包含了result,所以直接返回result
// 讲获取单例和创建登录框的方法解耦,符合开放封闭原则
var createLoginLayer = single.getSingle(login.createLayout)
oBtn.onclick = function() {
var layout = createLoginLayer()
layout.style.display = 'block'
}
</script>
</html>
小结:
1.单例模式的主要思想就是,实例如果已经创建,则直接返回
function creatSingleton() {
var obj = null
// 实例如已经创建过,直接返回
if (!obj) {
obj = xxx
}
return obj
}
最近拜读了曾探大神的《JavaScript设计模式与开发实践》,真是醍醐灌顶,犹如打通任督二脉的感觉,让我对JavaScript的理解加深了很多。
本文中关于各种设计模式定义都是引用书中的,部分引用自百度百科已标出。另外,本文中所举例子大多是书中的,自已做了一些修改和补充,用ES6(书中都是ES5的方式)的方式实现,以加深自己对“类”的理解,并不是自己来讲解设计模式,主要是做一些笔记以方便自己过后复习与加深理解,同时也希望把书中典型的例子整理出来和大家分享,共同探讨和进步。
一提起设计模式,相信大家都会脱口而出,23种设计模式,五大设计原则。这里就不说了,奈何我功力远远不够啊。下面把我整理出的常用JavaScript设计模式按类型做个表格整理。本文较长,如果阅读起来不方便,可链接到我的github中,单独查看每一种设计模式。先整理这些,后续会继续补充,感兴趣的同学可以关注。
创建型
结构型
行为型
创建型模式
工厂模式
小结:
单例模式
举一个书中登录框的例子,代码如下:
小结:
1.单例模式的主要思想就是,实例如果已经创建,则直接返回
2.符合开放封闭原则
原型模式
在JavaScript中,实现原型模式是在ECMAScript5中,提出的Object.create方法,使用现有的对象来提供新创建的对象的__proto__。
更多关于prototype的知识可以看我之前的JavaScript中的面向对象、原型、原型链、继承,下面列一下关于prototype的一些使用方法
1. 方法继承
2. 所有函数默认继承Object
3. Object.create
4. isPrototypeOf
prototypeObj是否在obj的原型链上
5. instanceof
contructor.prototype是否出现在obj的原型链上
6. getPrototypeOf
Object.getPrototypeOf(obj) 方法返回指定对象obj的原型(内部[[Prototype]]属性的值)
7. setPrototypeOf
设置一个指定的对象的原型 ( 即, 内部[[Prototype]]属性)到另一个对象或 null
结构型模式
适配器模式
举一个书中渲染地图的例子
但是假如BaiduMap类的原型方法不叫show,而是叫display,这时候就可以使用适配器模式了,因为我们不能轻易的改变第三方的内容。在BaiduMap的基础上封装一层,对外暴露show方法。
小结:
代理模式
本文举一个使用代理对象加载图片的例子来理解代理模式,当网络不好的时候,图片的加载需要一段时间,这就会产生空白,影响用户体验,这时候我们可在图片真正加载完之前,使用一张loading占位图片,等图片真正加载完再给图片设置src属性。
本例中,本体类中有自己的setSrc方法,如果有一天网络速度已经不需要预加载了,我们可以直接使用本体对象的setSrc方法,,并且不需要改动本体类的代码,而且可以删除代理类。
小结:
行为型模式
策略模式
迭代器模式
直接上代码, 实现一个简单的迭代器
ES6中的迭代器:
JavaScript中的有序数据集合包括:
注意: Object不是有序数据集合
以上有序数据集合都部署了Symbol.iterator属性,属性值为一个函数,执行这个函数,返回一个迭代器,迭代器部署了next方法,调用迭代器的next方法可以按顺序访问子元素
以数组为例测试一下,在浏览器控制台中打印测试如下:
小结:
JavaScript中的有序数据集合有Array,Map,Set,String,typeArray,arguments,NodeList,不包括Object
任何部署了[Symbol.iterator]接口的数据都可以使用for...of循环遍历
迭代器模式使目标对象和迭代器对象分离,符合开放封闭原则
观察者模式(订阅-发布模式)
先实现一个简单的发布-订阅模式,代码如下:
以上代码可以满足先订阅后发布,但是如果先发布消息,后订阅就不满足了。这时候我们可以稍微修改一下即可满足先发布后订阅,在发布消息时,把事件缓存起来,等有订阅者时再执行。代码如下:
小结:
命令模式
在命令的发布者和接收者之间,定义一个命令对象,命令对象暴露出一个统一的接口给命令的发布者,而命令的发布者不用去管接收者是如何执行命令的,做到命令发布者和接收者的解耦。
举一个如果页面中有3个按钮,给不同按钮添加不同功能的例子,代码如下:
状态模式
举一个关于开关控制电灯的例子,电灯只有一个开关,第一次按下打开弱光,第二次按下打开强光,第三次按下关闭。
如果这时候需要增加一个超强光,则只需增加一个超强光的类,并添加pressBtn方法,改变强光状态下,点击开关需要把状态更改为超强光,超强光状态下,点击开关把状态改为关闭即可,其他代码都不需要改动。
小结:
终于到最后可,历时多日地阅读与理解,并记录与整理笔记,目前整理出10中JavaScript中常见的设计模式,后续会对笔记继续整理,然后加以补充。由于笔者功力比较浅,如有问题,还望大家多多指正,谢谢。
参考链接:
JavaScript设计模式与开发实践
深入理解JavaScript系列/设计模式--汤姆大叔的博客
设计模式--菜鸟教程
JavaScript 中常见设计模式整理
ES6入门--阮一峰
The text was updated successfully, but these errors were encountered: