设计模式

110 阅读4分钟

类创建的设计模式

构造器模式

例如:动态创建li的每个项来显示对象的属性

class Student{
    constructor(name,age){
        this.name = name;
        this.age = age;
    }
    sayHi(){
        console.log(this.name + ':Hi')
    }
}
function Student1(name,age){
    this.name = name;
    this.age = age;
}
Student1.prototype.setHi = function(){
    console.log(this.name + ':Hi')
}
let s1 = new Student()

创建者模式

使用于对每个构造对象进行一些属性的判断或者得到创建对象的数量等。例如表单校验效果

//创建者模式
class Student{
    constructor(name,age){
        this.name = name;
        this.age = age;
    }
    ...
}
class StudentBuilder{
    constructor(name,age){
        this.student = new Student(name,age)
    }

    setSex(sex){
        if(sex != '男' || sex != '女') throw '性别错误'
        this.student.sex = sex
    }

    builder(){
        //可以在这做统计学生数量等操作
        return this.student;
    }
}

let sb = new StudentBuilder();
sb.setSex('男');
let s = sb.builder()

工厂模式(重)

//工厂模式
class Student {...}
class factory(name,type){
    switch(type){
        case '文科':
            return new Student(name,['政治','历史'])
            break;
        case '理科':
            return new Student(name,['数学','物理'])
            break;
        default:
            throw '没有该专业';
    }
}

let s1 = factory('学生1','文科')
let s2 = factory('学生2','理科')

抽象工厂模式

//抽象工厂
class Student {...}
class Teacher {...}
function studentFactory(...){
    return new Student(...)
}
function teacherFactory(..){
    return new Teacher(...)
}
function userProducer(factory){
    switch(factory){
        case 'student':
            return studentFactory;
            break;
        case 'teacher':
            return teacherFactory;
        default:
            throw '没有这个工厂';
            break;
    }
}
var factory = userProducer('teacher')//返回一个对应的工厂
var t = factory('老师1','特级')

单例模式(重)

例如一个系统的财务共享,弹窗(只有一个),登录注册(判断用户是否登录)

//单例模式
function Resource() {
    if(Resource.instance){
        return Resource.instance;
    }else{
        this.money = 100;
        Resource.instance = this;
    }
}
//=>
class Person{
    constructor(){
        if(Person.instance){
            return Person.instance
        }else{
            Person.instance = this
        }
    }
}
let r = new Resource()
r.money = 50

let r1 = new Resource()
console.log(r1.money)//50

适配器模式

例如全局把$.ajax改为使用axios形式;axios内部也是根据浏览器环境和node环境进行适配来进行请求发送

function toAxiosAdaptor(options){
    return axios({
        url: options.url,
        methods: options.type
    }).then(options.success,options.error)
}
$.ajax = function (options){
    return toAxiosAdaptor(options)
}

装饰器模式

不想破坏原来的构造函数,使用外部方法来实现某些功能的添加或者属性和方法的添加。

//不使用装饰器模式
class Student {
    constructor(){...}
    addClass(class){
        this.class = class
    }
}

//使用装饰器模式
class Student {}
function addClass(student,class){
    student.class = class
}

组合模式

部分组合成一个需要的东西,例如表单,不同的表单需要的东西不一样,把每个拆分成一个个组件排列组合就可以了

观察者模式(发布订阅模式)

//观察者模式
class MsgCenter{
    constructor(){
        this.msgCenter = {}
    }
    //订阅
    subscribe(type,fn){
        if(this.msgCenter[type]){
            this.msgCenter[type].push(fn)
        }else{
            this.msgCenter[type] = [fn]
        }
    }
    //发布
    publish(type,info){
        let params = {
            type: type,
            info: info
        }
        //遍历type数组执行里面的方法
        this.msgCenter[type].forEach(msg => {
            msg(params)
        })
    }
    //取消
    cancel(type,fn){
        if(this.msgCenter[type]){
            for(let i = 0;i<this.msgCenter[type].length;i++){
                if(this.msgCenter[type][i] == fn){
                    this.msgCenter[type].splice(i,1)
                }
            }
        }
    }
}

let msgCenter = new MsgCenter()

//消息订阅
msgCenter.subscribe('channel1',function(e){
    console.log('1-1订阅了'+e.type+'。得到的最新发布信息为:'+e.info.msg)
})
msgCenter.subscribe('channel1',function(e){
    console.log('1-2订阅了'+e.type+'。得到的最新发布信息为:'+e.info.msg)
})
msgCenter.subscribe('channel1',function(e){
    console.log('1-3订阅了'+e.type+'。得到的最新发布信息为:'+e.info.msg)
})

msgCenter.subscribe('channel2',function(e){
    console.log('2-1阅了'+e.type+'。得到的最新发布信息为:'+e.info.msg)
})

msgCenter.subscribe('channel3',function(e){
    console.log('3-1阅了'+e.type+'。得到的最新发布信息为:'+e.info.msg)
})
let fn2 = function(e){
    console.log('3-2订阅了'+e.type+'。得到的最新发布信息为:'+e.info.msg)
}
msgCenter.subscribe('channel3',fn2)


//消息发布
msgCenter.publish('channel1',{msg: '通道1发布了一条信息'})
msgCenter.publish('channel2',{msg: '通道2发布了一条信息'})
msgCenter.publish('channel3',{msg: '通道3发布了一条信息'})

msgCenter.cancel('channel3',fn2)
msgCenter.publish('channel3',{msg: '通道3发布了一条信息'})

/**打印
1-1订阅了channel1。得到的最新发布信息为:通道1发布了一条信息
1-2订阅了channel1。得到的最新发布信息为:通道1发布了一条信息
1-3订阅了channel1。得到的最新发布信息为:通道1发布了一条信息

2-1阅了channel2。得到的最新发布信息为:通道2发布了一条信息

3-1阅了channel3。得到的最新发布信息为:通道3发布了一条信息
3-2订阅了channel3。得到的最新发布信息为:通道3发布了一条信息

3-1阅了channel3。得到的最新发布信息为:通道3发布了一条信息
**/

策略模式

存在多种状态或者策略需要进行选择,将所有选择封装在一起,只给外部暴露出必要的接口。例如验证表单规则 (也可以使用构造函数的形式来弄,下面是直接使用对象的形式) image.png

image.png

链模式(每个方法里return this)

实现实例的链式调用,例如jq/zepto(去掉兼容的jq)源码都使用这种模式 image.png

命令模式

代理者模式(委托模式)

当多个对象需要处理统一事件处理时候,可以将这些事件交由另一个对象同一处理。例如事件委托处理。