设计模式
什么是设计模式
假设有一个空房间,我们要日复一日地往里 面放一些东西。最简单的办法当然是把这些东西 直接扔进去,但是时间久了,就会发现很难从这 个房子里找到自己想要的东西,要调整某几样东 西的位置也不容易。所以在房间里做一些柜子也 许是个更好的选择,虽然柜子会增加我们的成 本,但它可以在维护阶段为我们带来好处。使用 这些柜子存放东西的规则,就是一种模式
学习设计模式,有助于写出可复用和可维护性高的程序
常用的设计模式
单例模式
定义
保证一个类仅有一个实例,并提供一个访问它的全局访问点
核心
确保只有一个实例,并提供全局访问
优点
- 内存中只有一个实例,减少了内存的开销。
- 避免了对资源多重的占用。
缺点
- 违反了单一职责,一个类应该只关心内部逻辑,而不用去关心外部的实现
装饰模式
定义
- 装饰者模式能够在不更改源代码自身的情况下,对其进行职责添加。相比于继承装饰器的做法更轻巧。通俗的讲我们给心爱的手机上贴膜,带手机壳,贴纸,这些就是对手机的装饰。
优点
- 装饰类和被装饰类它们之间可以相互独立发展,不会相互耦合,装饰器模式是继承的一个替代模式,它可以动态的扩展一个实现类的功能。
缺点
- 多层的装饰会增加复杂度
实现
- 在编写飞机大战的游戏中,飞机对象的攻击方式只有普通子弹攻击,如何在不更改原代码的情况下,为它其他的攻击方式,如激光武器,导弹武器?
class Aircraft {
ordinary(){
console.log('发射普通子弹')
}
}
class AircraftDecorator {
constructor(aircraft){
this.aircraft = aircraft
}
laser(){
console.log('发射激光')
}
guidedMissile(){
console.log('发射导弹')
}
ordinary(){
this.aircraft.ordinary()
}
}
const aircraft = new Aircraft()
const aircraftDecorator = new AircraftDecorator(aircraft)
aircraftDecorator.ordinary() // 发射普通子弹
aircraftDecorator.laser() // 发射激光
aircraftDecorator.guidedMissile() // 发射导弹
观察者模式
定义
观察者模式,它定义对象之间的1对N的依赖关系,当其中一个对象发生变化时,所有依赖于它的对象都会得到通知。
生活中的观察者模式
每次小米出新款手机都是热销,我看中了小米3这款手机,想去小米之家购买,但是到店后售货员告诉我他们这款手机很热销,他们已经卖完了,现在没有货了,那我不可能每天都跑过来问问吧,这样很耽误时间的,于是我将我的手机号码留给销售小姐姐,如果他们店里有货,让她打电话通知我就好了,这样就不用担心不知道什么时候有货,也不需要天天跑去问了,如果你已经成功买到了手机呢,那么销售小姐姐之后也就不需要通知你了~
优点
- 观察者和被观察者它们之间是抽象耦合的。并且建立了触发机制。
缺点
- 当订阅者比较多的时候,同时通知所有的订阅者可能会造成性能问题。
- 在订阅者和订阅目标之间如果循环引用执行,会导致崩溃。
- 发布订阅模式没有办法提供给订阅者所订阅的目标它是怎么变化的,仅仅只知道它变化了。
实现
- 比如前段时间的冬奥会,项目还没有开始的时候可以提前预定,等到项目快开始的时,APP会提前给我们发送通知即将开始的项目,而没到时间的不通知,另外在项目还没有开始的时候,可以取消订阅避免接受到通知。根据这个需求我们来写一个例子吧
function Observer(){
}
Observer.prototype.update=function(){
console.log('工作')
}
function ObserverList(){
this.list = [];
}
ObserverList.prototype.add=function(obj){
this.list.push(obj)
}
ObserverList.prototype.empty=function(){
this.list=[];
}
ObserverList.prototype.remove=function(obj){
for(let i=0;i<this.list.size;i++){
if(list[i]==obj){
this.list.splice(0,1,obj);
return;
}
}
}
function Subject(){
this.objserverList=new ObserverList();
this.state=null;
}
Subject.prototype.addObser=function(observe){
this.objserverList.add(observe)
}
Subject.prototype.removeObser=function(observe){
this.objserverList.remove(observe)
}
Subject.prototype.notify=function(){
let list = this.objserverList.list
list.forEach(e=>{
e.update();
})
}
Subject.prototype.setState=function(newState){
this.state= newState;
this.notify();
}
Subject.prototype.getState=function(){
return this.state;
}
利用 Proxy 很轻松的实现:
const obj = new Proxy(obj, {
get(target,key) {}
set(target,key,value) {}
})
renderTable(obj)
renderChart(obj)