大家好,我是右子。
设计模式千千万,一个不中接着换。
我们在这里看一下JS中的都有那些设计模式吧。
什么是设计模式
设计模式是解决问题的一种思想,和语言无关。在面向对象软件设计的工程中,针对特定的问题简洁优雅的一种解决方案。
通俗一点的说,设计模式就是符合某种场景下某个问题的解决方案,通过设计模式可以增加代码的可重用性,可扩展性,可维护性,使得我们的代码高内聚、低耦合。
构造器模式
function Foo(name,age){
this.name = name;
this.age = age;
this.say = function(){
console.log(this.name,this.age);
}
};
let fn = new Foo("小明",18);
fn.say(); // 小明 18
优点:
- 构造器模式,可以充分复用代码。
缺点:
- 每次new之后,方法内的属性都会重新申请内存空间,应该把可公共的提取到原型中。
原型模式
function Foo(name,age){
this.name = name;
this.age = age;
};
Foo.prototype.say = function(){
console.log(this.name,this.age);
};
let fn = new Foo("小明",18);
fn.say(); // 小明 18
优点:
- 工厂模式,可以将可复用的属性或方法放到原型中,减少内存占用。
原型模式我们还可以用ES6推出的Class写法,更简洁方便,它是构造器模式和原型模式的集合体。
Class Foo{
constructor(name,age){
this.name = name;
this.age = age;
}
// 方法会被添加到prototype中,并且是不可枚举的。
say(){
console.log(this.name,this.age);
}
};
let fn = new Foo("小明",18);
fn.say(); // 小明 18
Class的写法也可以用函数实现,这里已经了解的小伙伴可以跳过~
Class的规范要求:
- 要求严格模式
- 只能通过new来调用
- 函数不可枚举
- 方法本身不能使用new
"use strict";
function Foo(name,age){
if( !(this instanceof Foo) ){
throw new TypeError("必须通过构造函数new才能调用!");
}
this.name = name;
this.age = age;
};
Object.defineProperty(Foo.prototype,"say",{
value(){
if( !(this instanceof Foo) ){
throw new TypeError("不可通过new调用!");
}
console.log(this.name,this.age);
},
enumerable: false
});
工厂模式
- 工厂模式决定创建对象类的实例,主要用来创建同一类的对象。
Class Factory{
constructor(role,page){
this.role = role;
this.page = page;
}
static purview(role){
switch(role){
case "superamin":
return new Factory("supermain",["home","detail"]);
break;
case "editor":
return new Factory("editor",["detail"]);
break;
default:
return throw Error("传入的参数不正确");
}
}
}
Factory.purview("superamin");
优点:
- 通过工厂模式,我们可以快速创建大量相似对象,没有重复代码。
策略模式
- 定义一系列算法,并将算法封装起来,使他们可以相互替换。
let list = {
"admin": ["home","detail"],
"editor": ["detail"]
};
Class Foo{
constructor(data){
this.list = data;
}
bound(role){
return this.list[role];
}
}
let fn = new Foo(list);
fn.bound("admin") // ["home","detail"]
优点:
- 具有易维护,易扩展的特点。
- 避免多重if else的判断,解决代码编写复杂性。
观察者模式
- 观察者模式有观察目标、观察者两类对象。
- 观察目标可以添加多个观察者。
- 目标发生状态变更,所有观察者都会接到通知。
class Subject{
constructor(){
this.obs = [];
}
// 绑定/添加
add(){
this.obs = this.obs.push(ob);
}
// 删除
remove(ob){
this.obs = this.obs.filter(item=> item!==ob);
}
// 通知
notify(){
this.ob.forEach(item=>{
item.update();
});
}
}
class Observer{
constructor(){
}
update(){
console.log("更新");
}
}
const serve1 = new Observer();
const serve2 = new Observer();
const sub = new Sub();
sub.add(serve1);
sub.add(serve2);
// 2秒后通知所有观察者
setTimeout(()=>{
sub.notify();
},2000);
优点:
- 目标与观察者功能耦合度降低,专注自身功能逻辑;
缺点:
- 对事件通知不能进行细分管控。
发布订阅模式
- 发布者和订阅者不用互相通知,通过“第三方”实现调度,属于经过解耦的观察者模式。
class PubSub{
constructor(){
this.msgs = {};
}
publish(key,data){
this.msg[key] && this.msg[key].forEach(item=> {
if(typeof item==="function"){
item(data);
}
});
}
subscribe(key,cb){
if(!this.msgs[key]){
this.msgs = [cb];
}else{
this.msgs.push(cb);
}
}
unsubscribe(key,cb){
if(!this.msg[key]){
return
}
// 清除所有
if(!cb){
this.msg[key].length = 0;
}else{
this.msg[key] = this.msg[key].filter(item=> item!===cb);
}
}
}
优点:
- 可以对事件通知,进行细分管控。