待更新 补全代码部分设计模式的demo
设计模式是一套反复使用多数知晓的、经过分类的、代码设计经验总结
任何事情都有套路,设计模式,就是写代码中常见套路,有些写法我们一直在用
订阅/发布模式(观察者)
pub/sub 这个应该大家⽤用到最⼴的设计模式了,
在这种模式中,并不是一个对象调用另一对象的方法,而是一个对象订阅另一对象特定活动并在状态改变收获得通知,订阅着因此也成为观察者,而被观察者的对象成为发布者或着主题,当发生一个重要事件时候发布者会通知(调用)所有订阅者并且可能经常已事件对象的形式传递消息
class observer {
constructor() {
this.observerCache = {} // 储存
}
$on(name,cb) {
(this.observerCache[name]||(this.observerCache[name] = [])).push(cb)
}
$emit(name,args) {
if (this.observerCache[name]) {
this.observerCache[name].forEach(item=>{
item.call(this,args)
});
} else {
console.warn('observerCache没有相对应的name')
}
}
$off(name) {
if (this.observerCache[name]) {
this.observerCache[name] = null;
} else {
console.warn('observerCache没有相对应的name')
}
}
}
单例模式
单例模式的定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点。实现的方法为先判断实例存在与否,如果存在则直接返回,如果不存在就创建在返回,这就是确保一个类只有一个实例对象
适用场景: 一个单一对象,比如弹窗,无论点击多少次,弹窗只应该被创建一次,实现起来也简单,用一个变量缓存即可
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.model-alert {
background-color: red;
width: 100px;
height: 100px;
position: absolute;
}
</style>
</head>
<body>
<button id='model-btn'>
一个弹窗
</button>
<button id='model-btn1'>
两个
</button>
</body>
<script>
let instance=null;
function createAlertfn(fn,alertcontent) {
console.log(instance)
if (instance) {
instance.innerHTML = alertcontent
}
return instance || (instance = fn.call(this,alertcontent))
}
function createAlertHtml(alertcontent) {
let div = document.createElement('div');
div.innerHTML = alertcontent||'我是弹窗';
div.className = 'model-alert';
if (instance) return
div.style.display = 'none';
document.body.append(div);
return div
}
document.getElementById('model-btn').addEventListener('click',() => {
let div = createAlertfn(createAlertHtml,'我是1')
console.log(div)
div.style.display = 'block'
},false)
document.getElementById('model-btn1').addEventListener('click',() => {
let div = createAlertfn(createAlertHtml,'我是2')
console.log(div)
div.style.display = 'block'
},false)
</script>
</html>
策略模式
策略模式的定义:定义一系列的算法,把他们一个个封装起来 并且使他们可以相互替换
策略模式java定义:定义算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户
其实核心都是让客户直接执行,不用管这个操作具体是怎么执行的
策略模式的目的就是将算法的使用,算法的实现分离开来。
一个基于策略模式的程序至少由两部分组成,第一部分是一组策略模式(可变),策略封装了具体的算法,并负责具体的计算过程,第二个部分是环境类(context)不看,context接受客户的请求,随后将请求委托给某一个策略类,要做到这一点,说明context中要维持对某个策略对象的引用
代理模式
代理模式定义:为一个对象提供一个代用品或占位符以便控制对他的访问
常用的虚拟代理形式:某个花销很大的操作,可以通过虚拟代理的方式延迟到这种需要它的时候才去创建(例如:使用虚拟代理实现图片懒加载)
图片懒加载的方式:先通过一张loading图占位,然后通过异步的方式加载图片,等图片加载好了再把完成的图片加载到img标签里面
防抖截流 https://www.cnblogs.com/momo798/p/9177767.html
中介者模式
中介者模式的定义:通过一个中介者对象,其他所有的相关对象都通过该中介者对象来通信,而不是互相引用,当其中的一个对象发生改变时,只需要通知中介者即可,通过中介者模式可以解除对象与对象之间的紧耦合关系
例如 redux、vuex都属于中介者模式的实际应用,我们啊吧共享的数据,抽离成一个单独的store,每个都通过store这个中介者来操作对象
装饰器模式
装饰器模式的定义:在不改变自身对象的的基础上,在程序运行期间给对象动态地添加方法,常见应用,react的高阶组件,或者react-dedux中的@connect或者自己定义一些高阶组件
Function.prototype.before = function (beforeFn) {
var _this =this;
return function () {
beforeFn.call(_this,arguments);
return _this.apply(_this,arguments)
}
};
Function.prototype.after = function (beforeFn) {
var _this =this;
return function () {
var ret = _this.apply(_this,arguments)
beforeFn.call(_this,arguments);
return ret
}
};
外观模式
外观模式即让多个方法一起被调用涉及到兼容性,参数支持多格式,有很多这种代码,对外暴露统一的api,比如上面的off参数支持多个情况,对面只有一个函数,内部判断实现
工厂模式
提供创建对象的接口,吧成员对象的创建工作转角给一个外部对象,好处在于对象质检的耦合(也就是相互影响)
常见例子,我们的弹窗或者Message的实例,就是典型的工厂模式
建设者模式
和工厂模式相比,参与了更多的创建过程(就过程来说 只是工厂模式的加强版)
迭代器模式
迭代器模式是指提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示,迭代器模式可以把迭代的过程从业务逻辑中分离处理,在使用迭代器模式之后,即使不关心独享的内部构造,也可以按顺序访问其中的每个元素
es6支持有api支持这种模式比如 map ,foreach,some,filter,every
享元模式
享元模式是一种用于性能优化的模式,‘fly’在这里是苍蝇的意思意为蝇量级,享元模式的核心是运用共享技术来有效支持大量细粒度的对象,如果系统中因为创建大量类似的对象而导致内存占用度过高,享元模式就非常有用,在javascript中,浏览器特别是移动端的浏览器分配的内存并不算多,如何节省内存就成了一件非常有意义的事情
假设有个内衣工厂,目前的产品有50中男式内衣和50中女士内衣,为了推销产品,工厂决定生产一些塑料模特来穿上内衣拍广告,正常情况需要50个男模特和50个女模特,然后让他们每人分别穿上一件内衣来拍照
会用到享元模式的情况
内部状态存储于对象内部
内部状态可以被一些对象共享
内部状态独立于具体的场景,通常不会改变
外部状态取决于具体的场景,并根据场景而变化,外部状态不能被共享
性别是内部状态,内衣是外部状态,通过区分这两种张状态,大大减少了系统中的对象数量,通常来讲,内部状态有多少种组合,系统中变最多存多少个对象,因为性别通常只有男女两种,所以该内衣厂商最多需要2个对象
职责链模式
职责链模式的定义是:使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系,将这些对象连成一条链,并沿着这条传递链该请求,直到有一个对象处理它为止。职责链模式的名字非常形象,一系列可能会处理请求的对象被连成一条链,请求在这些对象之间依次传递,直到遇到一个可以处理它的对象,我们把这些对象成为链的节点
职责链模式更方便扩展方法
例:假设我们负责一个售卖手机的电商网站,经过分别交纳500元定金和200元定金的两轮预定后(订单已在此时生成),现在已经到了正式购买的阶段,公司针对支付过定金的用户有一定的优惠政策。在正式购买后,已经支付过的500元定金的用户会收到100元优惠卷,200元定金的用户会收到50元优惠卷,而之前没有支付定金的用户只能进入普通模式购买,也就是没有优惠卷,且在库存有限的情况下不一定保证可以买到。
适配器模式
适配器模式得作用是解决两个软件实体间得接口不兼容的问题。使用适配器模式之后,原本由于接口不兼容而不能工作的两个软件实体可以一起工作,适配器的别名是包装器(wrapper),这是一个相对简单的模式。在程序开发中有许多这样的场景:当我们试图调用模块或者对象的某个 接口时,却发现这接口的格式并不符合目前的需求。这个时候有两种解决办法,第一种修改原来的接口实现,但是如果原来模块很复杂,或者我们拿到的模块是一段别人编写的经过压缩的代码,修改愿接口就显得不太现实。第二种办法就是创建一个适配器,将原来的接口转换为客户希望的另一个接口,客户只需要和适配器打交道
lowdb的适配器应用:https://github.com/typicode/lowdb/blob/master/src/adapters/FileAsync.js
模版方法模式
模版方法模式在一个方法中定义一个算法的骨架,而将一些步骤的实现延迟到子类中。模版方法是的子类可以在不改变算法结构的情况下,重新定义算法中某些步骤的具体实现
例如: vue的slot react的children
备忘录模式
可以恢复到对象之前的某个状态,react或redux就有时间旅行模式,就算备忘录的一种
简单的说就是把每次更新的状态全部都记录下来,让用户可以反悔
组合模式
定义:将对象组合成属性结构以表示'树形-整体'的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
14 * 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
14 * 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
生成器模式
定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
设计模式的总结
创建设计模式:工厂、单例、建造者、原型
结构化设计模式:外观、适配器、代理、装饰器、享元、桥接、组合
行为模式: 策略、模版方法、观察者、迭代器、责任链、命令、备忘录、状态、访问者、终结器、解释器
网友评论