Open gdutwyg opened 5 years ago
保证一个类仅有一个实例,并提供一个访问它的全局访问点。实现的方法为先判断实例存在与否,如果存在则直接返回,如果不存在就创建了再返回,这就确保了一个类只有一个实例对象。
class Fn { constructor(name) { this.name = name } getName() { return this.name; } } // 代理实现单例模式 var ProxyMode = (function() { var instance = null; return function(name) { if(!instance) { instance = new Fn(name); } return instance; } })(); // 测试单体模式的实例 var a = new ProxyMode("aaa"); var b = new ProxyMode("bbb"); // 因为单体模式是只实例化一次,所以下面的实例是相等的 console.log(a === b); //true console.log(a.getName()); //aaa console.log(b.getName()); //aaa
常见的实例化对象模式,工厂模式就相当于将 new 操作单独封装,只对外提供相应接口
// 定义产品 class Product { constructor (name) { this.name = name; } init () {} } // 定义工厂 class Factory { create (name) { return new Product(name); } } const factory = new Factory(); const p = factory.create('bbb'); // 通过工厂对象创建出来的产品
用来解决两个接口不兼容问题,由一个对象来包装不兼容的对象,比如参数转换,允许直接访问
class Adapter { specificRequest () { return '德国标准插头'; } } // 适配器对象,对原来不兼容对象进行包装处理 class Target { constructor () { this.adapter = new Adapter(); // 实例化Adapter } request () { const info = this.adapter.specificRequest(); console.log(`${info} - 转换器 - 中国标准插头`) } } const target = new Target(); console.log(target.request()); // 德国标准插头 - 转换器 - 中国标准插头
在不改变对象自身的基础上,动态的给某个对象添加新方法,同时又不影响旧方法
class Circle { draw() { console.log('画一个圆形'); } } class Decorator { constructor(circle) { this.circle = circle; } draw() { this.circle.draw(); this.setRedBorder(circle); } setRedBorder(circle) { console.log('画一个红色边框'); } } let circle = new Circle(); let decorator = new Decorator(circle); // 把circle实例传入 //画一个圆形 // 画一个红色边框 decorator.draw();
该例中,我们写了一个Decorator装饰器类,它重写了实例对象的draw方法,给其方法新增了一个setRedBorder(),因此最后为其输出结果进行了装饰。
为其他对象提供一种代理,便以控制对这个对象的访问,不能直接访问目标对象
// 为这个target设置一个代理 class Target { constructor () { } test () { console.log('test') } } class ProxyObj { constructor () { this.target = new Target() } test () { this.target.test() } } let proxy = new ProxyObj() proxy.test()
通过一个中介者对象,其他所有的相关对象都通过该中介者对象来通信,而不是相互引用,当其中的一个对象发生改变时,只需要通知中介者对象即可。通过中介者模式可以解除对象与对象之间的紧耦合关系。
例如:现实生活中,航线上的飞机只需要和机场的塔台通信就能确定航线和飞行状态,而不需要和所有飞机通信。同时塔台作为中介者,知道每架飞机的飞行状态,所以可以安排所有飞机的起降和航线安排。
中介者模式适用的场景:例如购物车需求,存在商品选择表单、颜色选择表单、购买数量表单等等,都会触发change事件,那么可以通过中介者来转发处理这些事件,实现各个事件间的解耦,仅仅维护中介者对象即可。
var colorSelect = document.getElementById('colorSelect'); var memorySelect = document.getElementById('memorySelect'); var numSelect = document.getElementById('numSelect'); //中介者 var mediator = (function() { return { changed: function(obj) { switch(obj){ case colorSelect: //TODO break; case memorySelect: //TODO break; case numSelect: //TODO break; } } } })(); colorSelect.onchange = function() { mediator.changed(this); }; memorySelect.onchange = function() { mediator.changed(this); }; numSelect.onchange = function() { mediator.changed(this); };
观察者模式,也叫订阅-发布模式, 该模式定义了一种1对N的关系(注意:不一定是一对多,所以更准确地描述应该是1对N),使观察者们同时监听某一个对象相应的状态变换,一旦变化则通知到所有观察者,从而触发观察者相应的事件。因此,观察者模式中的角色有两类:观察者(发布者)和被观察者(订阅者)
// 创建一个主题,保存状态,状态变化之后触发所有观察者对象 /* 每一个观察者(Observer)都有一个update 方法,并且观察者的状态就是等待被触发; 每一个主题(subject)都可以通过attach方法接纳N个观察者所观察,即观察者们存储在主题的observers数组里,; 主题有初始化状态(init)、获取状态(getState)和设置状态(setState)三个通用型方法; 当主题的状态发生变化时,通过特定的notifyAllObervers方法通知所有观察者。 */ class Subject { constructor() { this.state = 0; this.observers = [] } getState() { return this.state } setState(state) { this.state = state; this.notifyAllObservers() } notifyAllObservers() { this.observers.forEach(observer => { observer.update() }) } attach(observer) { this.observers.push(observer) } } // 观察者 class Observer { constructor(name , subject) { this.name = name; this.subject = subject; this.subject.attach(this); } update() { console.log(`${this.name} update, state: ${this.subject.getState()}`) } } const s = new Subject() var a = new Observer('a',s) var b = new Observer('b',s) var c = new Observer('c',s) s.setState(1) /* a update, state: 1 b update, state: 1 c update, state: 1 */
定义一系列的算法,把他们一个个封装起来,并且使他们可以相互替换。
/*策略类*/ 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
外观模式即让多个方法一起被调用
例如。 stopPropagation() 和 preventDefault() 兼容性一起调用。
var myEvent = { stop: function(e) { if (typeof e.preventDefault() === "function") { e.preventDefault(); } if (typeof e.stopPropagation() === "function") { e.stopPropagation(); } //for IE if (typeof e.returnValue === "boolean") { e.returnValue = false; } if (typeof e.cancelBubble === "boolean") { e.cancelBubble = true; } } } myEvent.stop()
JavaScript设计模式总结 JavaScript设计模式 js设计模式 javascript-design-patterns
单体模式
保证一个类仅有一个实例,并提供一个访问它的全局访问点。实现的方法为先判断实例存在与否,如果存在则直接返回,如果不存在就创建了再返回,这就确保了一个类只有一个实例对象。
工厂模式
常见的实例化对象模式,工厂模式就相当于将 new 操作单独封装,只对外提供相应接口
适配器模式
用来解决两个接口不兼容问题,由一个对象来包装不兼容的对象,比如参数转换,允许直接访问
装饰器模式
在不改变对象自身的基础上,动态的给某个对象添加新方法,同时又不影响旧方法
该例中,我们写了一个Decorator装饰器类,它重写了实例对象的draw方法,给其方法新增了一个setRedBorder(),因此最后为其输出结果进行了装饰。
代理模式
为其他对象提供一种代理,便以控制对这个对象的访问,不能直接访问目标对象
中介者模式
通过一个中介者对象,其他所有的相关对象都通过该中介者对象来通信,而不是相互引用,当其中的一个对象发生改变时,只需要通知中介者对象即可。通过中介者模式可以解除对象与对象之间的紧耦合关系。
例如:现实生活中,航线上的飞机只需要和机场的塔台通信就能确定航线和飞行状态,而不需要和所有飞机通信。同时塔台作为中介者,知道每架飞机的飞行状态,所以可以安排所有飞机的起降和航线安排。
中介者模式适用的场景:例如购物车需求,存在商品选择表单、颜色选择表单、购买数量表单等等,都会触发change事件,那么可以通过中介者来转发处理这些事件,实现各个事件间的解耦,仅仅维护中介者对象即可。
观察者模式
观察者模式,也叫订阅-发布模式, 该模式定义了一种1对N的关系(注意:不一定是一对多,所以更准确地描述应该是1对N),使观察者们同时监听某一个对象相应的状态变换,一旦变化则通知到所有观察者,从而触发观察者相应的事件。因此,观察者模式中的角色有两类:观察者(发布者)和被观察者(订阅者)
策略模式
定义一系列的算法,把他们一个个封装起来,并且使他们可以相互替换。
外观模式
外观模式即让多个方法一起被调用
例如。 stopPropagation() 和 preventDefault() 兼容性一起调用。