1. 单例模式:每个new出来的实例都需要有一个相同的方法,但是这时候如果 每个实例都新建一个这种方法,太占据内存也太慢,所以在这里有一个重要的判断:如果有实例,则返回实例;如果没有实例,则创建实例,并且返回实例。
例:
class CreateUser {
static shareInstance(){
if(!CreateUser.ins){
CreateUser.ins = new CreateUser('aa')
}
return CreateUser.ins;
}
constructor(name) {
this.name = name;
this.getName();
}
getName() {
return this.name;
}
}
let c1 = CreateUser.shareInstance()
let c2 = CreateUser.shareInstance()
console.log(c1==c2)
2. 组合模式:组合模式中基本对象和组合对象被一致对待;无须关心对象有多少层, 调用时只需在根部进行调用;类似DOM树
例:
const MacroCommand = function() {
return {
lists: [],
add: function(task) {
this.lists.push(task)
},
excute: function() { // 组合对象调用这里的 excute,
for (let i = 0; i < this.lists.length; i++) {
this.lists[i].excute()
}
},
}
}
const command1 = MacroCommand() // 命令1
command1.add({
excute: () => console.log('吃饭') //
})
const command2 = MacroCommand() // 命令2
command2.add({
excute: () => console.log('唱歌')
})
command2.add({
excute: () => console.log('画画')
})
const command3 = MacroCommand() //命令3
command3.add({
excute: () => console.log('下棋')
})
command3.add({
excute: () => console.log('玩游戏')
})
const macroCommand = MacroCommand()//组合对象
macroCommand.add(command1)
macroCommand.add(command2)
macroCommand.add(command3)
macroCommand.excute()
// 吃饭
// 唱歌
//画画
// 下棋
// 玩游戏
3. 观察者模式:类似于事件监听, 观察者只要订阅了被观察者的事件,那么当被观察者的状态改变时,被观察者会主动去通知观察者,而无需关心观察者得到事件后要去做什么,实际程序中可能是执行订阅者的回调函数
例:
var obj = {
data: {
list: []
},
}
// defineProperty 可以观察 obj对象 的list 属性的使用
Object.defineProperty(obj, 'list', {
get() {
console.log('获取了list 属性')
console.log(this.data['list'])
return this.data['list']
},
set(val) {
console.log('值被更改了')
this.data['list'] = val
}
})
// 获取了list属性,那么get 方法就会被调用
console.log(obj.list)
// 设置了list属性set 方法就会被调用
obj.list = ['a', 'b']
4. 工厂模式: 去做同样的事情,实现同样的效果,批量生产
例:
// 文本工厂
class Text {
constructor(text) {
this.text = text
}
insert(where) {
const txt = document.createTextNode(this.text)
where.appendChild(txt)
}
}
// 链接工厂
class Link {
constructor(url) {
this.url = url
}
insert(where) {
const link = document.createElement('a')
link.href = this.url
link.appendChild(document.createTextNode(this.url))
where.appendChild(link)
}
}
5. 抽象的工厂模式:先标记好模式,然后下面引用,但是里面什么都没有
class DomFactory {
constructor() {
}
// 各流水线
insert() {
}
}
6. 策略模式:策略类部分和环境类部分
①策略类:写出好几种策略,类似于planA,planB….
例:
var levelOBJ = {
"A": function (money) {
return money * 4;
},
"B": function (money) {
return money * 3;
},
"C": function (money) {
return money * 2;
}
};
/*环境类*/
var calculateBouns = function (level, money) {
return levelOBJ[level](money);
};
console.log(calculateBouns('A', 10000)); // 40000
②环境类:运行的环境
7. 代理模式:经典例子:刚打开页面的时候加载个loading图片占位,等图片加载过来后再显示该图片,提前占坑
例:
const MyImage = function (parent) {
const imgNode = document.createElement('img')
parent.appendChild(imgNode)
// 提供一个方法 ,让外部也能修改 图片的src属性
this.setSrc = function(src){
imgNode.src = src
}
}
// 直接添加图片 ,如果图片比较大,可能加载的比较慢,导致网页上的img一开始显示不出来
let myImage = new MyImage(document.body)
// 写个代理 提供 预加载功能
const ProxyImage = function (myImage) {
// 创建image对象
const img = new Image()
img.on
// 监听img对象的 onload 方法
img.onload = function () { // http 图片加载完毕后才会执行
// 模拟网络很慢的情况
setTimeout(()=>{
myImage.setSrc(this.src)
},2000)
}
this.setSrc =function (src) {
// 加载时候先不加载大图,先加载一张小图(浏览器已经下载过的)
myImage.setSrc('loading.gif') // 本地 loading 图片
img.src = src
}
}
//
let proxyImage = new ProxyImage(myImage)
proxyImage.setSrc('https://www.baidu.com/img/bd_logo1.png?where=super')
8. 适配器模式:类似于把obj对象转为数组,这时候如果是大量的操作怕出意外,就可以运用这种模式,就相当于有个中介转一下
例:
// 老接口
const zhejiangCityOld = function () {
return [{
name: 'hangzhou',
id: 11,
},
{
name: 'jinhua',
id: 12
}
]
}
console.log(zhejiangCityOld())
// 新接口希望是下面形式
// {
// hangzhou: 11,
// jinhua:12
// }
// 这时候就可采用适配者模式
const adaptor = function (oldCity) {
console.log(oldCity)
const obj = {}
for (let city of oldCity) {
obj[city.name] = city.id
}
return obj
}
let oldData = zhejiangCityOld();
//把老数据放在适配器中产生新数据
console.log(adaptor(oldData))
既然看了这么多设计者模式,接下来也可以了解一下hash,它在我们的应用中也很重要:
1.Hash:传统的网页根据用户访问的不同地址,浏览器从服务器获取对应页面的内容展示给用户,这样造成服务器压力比较大,用户访问比较慢,在这种场景下,出现了单页应用。
2. Hashchange:想要用hash就要监听到hash什么时候改变,这时候就需要用hashchange来监听