zhh10 / Notes

前端中react、Vue、ES6、css3、webpack、模块化等思维导图
12 stars 1 forks source link

设计模式 #29

Open zhh10 opened 4 years ago

zhh10 commented 4 years ago

简单工厂模式

封装在一个函数里面,通过这个函数可以创建需要的对象,这个函数通常被成为工厂函数,这种模式叫简单工厂模式

优点:

对于同一类对象在不同需求中的重复性使用,很多时候不需要重复创建,代码复用是面向对象变成的一条准则。通过对简单工厂来创建一些对象,可以让这些对象共用一些资源而又私有一些资源

缺点:

它的使用场合通常也就限制在创建单一对象

第一种方法


function BMW(){
this.info = '宝马'
}
BMW.prototype.getInfo = function(){
console.log(this.info)
}
function BENZ(){
this.info = '奔驰'
}
BENZ.prototype.getInfo = function(){
console.log(this.info)
}
function TESLA = function(){
this.info = '特斯拉'
}
TESLA.prototype.getInfo = function(){
console.log(this.info)
}

// 汽车工厂 function CarFactory(name){ switch(name){ case 'benz': return new BENZ() break; case 'bmw': return new BMW() break; case 'tesla' return new TESLA() break; } } var car = CarFactory('bmw') car.getInfo() //宝马

简单工厂模式的理念就是创建对象,像上面那种方式就是对不同的类实例化,不过除此之外,简单工厂模式还可以用来创建相似对象,可以通过相似的东西提取,不相似的针对性处理,

**只需简单创建一个对象,然后通过对这个对象大量拓展方法和属性,并在最终对象返回出来**

> 第二种方法
```js
// 汽车工厂
function carFactory(name,color,type){
        var car = new Object()
        car.name = name 
        car.whell = 4 
        car.color = color
        if(type === 'electric'){
            car.getInfo = function(){console.log('这是一辆电动车')}
        }
        if(type === 'oil'){
            car.getInfo = function(){console.log('这是一辆油气车')}
        }   
        return car
    }
    var car = carFactory('tesla','red','electric')
    console.log(car.name) 
    console.log(car.color) 
    console.log(car.whell)
    car.getInfo()
  1. 第一种是通过类实例化对象创建的
  2. 第二种是通过创建一个新对象然后包装增强其属性和功能来实现的
zhh10 commented 4 years ago

工厂方法模式

安全模式类

类的前面要加new关键字,如果使用的时候忽略了,会报错

var Demo = function(){}
Demo.prototype.show = function(){console.log('show')}

var demo = new Demo() 
demo.show() //'show'

var demo1 = Demo() 
demo1.show() //报错

安全模式就是为了解决这个问题

var Demo = function(){}
Demo.prototype.show = function(){
    if(!this instanceof Demo){
        return new Demo()
    }
}

var demo = new Demo() 
demo.show() //'show'

var demo1 = Demo() 
demo1.show() //报错

安全的工厂方法

function Factory(type,info){
    if(!(this instanceof Factory)){
        return new Factory(type,info)
    }else{
        return this[type](info)
    }
}
Factory.prototype = {
    'bmw':function(info){
        var car = new Object()
        car.info = '宝马'
        car.getInfo = function(){console.log(info)}
        return car
    },
    'benz':function(info){
        var car = new Object()
        car.info = '奔驰'
        car.getInfo = function(){console.log(info)}
        return car
    },
    'tesla':function(info){
        var car = new Object()
        car.info = '特斯拉'
        car.getInfo = function(){console.log(info)}
        return car
    },
}

var car = Factory('tesla','全球领先的新能源汽车品牌')
console.log(car.info)
car.getInfo()

工厂方法模式可以轻松创建多个类的实例对象,这样工厂方法模式对象在创建对象的方式也避免了使用者与对象类之间的耦合。

zhh10 commented 4 years ago

外观模式

为一组复杂的子系统借口提供一个更高级的统一接口,通过这个接口使得对子系统接口的访问更容易,简化了复杂底层接口不统一的使用需求。

类似于餐厅设计了一个套餐,来简化复杂的需求

function addEvent(dom,type,fn){
    //  如果浏览器支持addEventListener
    if(dom.addEventListener){
        dom.addEventListener(type,fn,false)
    }else if(dom.attachEvent){
        // 不支持addEventListener但支持attachEvent
        dom.attachEvent('on' + type,fn)
    }else{
        dom['on' + type] = fn
    }
}

var myDom = document.getElementById('app')
addEvent(myDom,'click',()=>{console.log(123)})

获取事件对象

function getEvent(event){
    //  IE 是 window.event
    return event || window.event
}

获取元素

function getTarget(event){
    var event = getEvent(event)
    return event.target || event.srcElement
}

阻止默认行为

function preventDefault(event){
    var event = getEvent(event) 
    if(event.preventDefault){
        event.preventDefault()
    }else{
        //IE浏览器
        event.returnValue = false
    }
}
document.onclick = function(e){
    e = getEvent(e) 
    preventDefault(e)
}
zhh10 commented 4 years ago

适配器模式

将一个类(对象)的接口(方法或属性)转化为另外一个接口,以满足用户需求,使类(对象)之间接口的不兼容问题通过适配器得以解决

为两个代码库所写的代码兼容书写的额外代码

适配异类框架

A.g = function(id){
    return $(id).get(0)
}
A.on = function(id,type,fn){
    var dom = typeof id === 'string' ? $('#'+id) : $(id)
    dom.on(type,fn)
}

参数适配器

当不知道传递的参数是否完整时,一些参数需要设置默认值,通常使用适配器来适配传入的这个参数对象

function doSomeThing(obj){
    var obj_ = {
        name:'admin',
        age:18,
        title:'设计模式',
        size:100,
    }
    var obj = Object.assign(obj_,obj)
    return obj
}
zhh10 commented 4 years ago

观察者模式

var Observer = class{
    constructor(){
        this._message = {}
    }
    regist(type,fn){
        if(typeof this._message[type] === 'undefined'){
            this._message[type] = [fn]
        }else{
            this._message[type].push(fn)
        }
    }
    cancel(type,fn){
        if(this._message[type] instanceof Array){
            for(let i = 0;i<this._message[type].length - 1;i++){
                this._message[type][i] === fn ? this._message[type].splice(i,i):null
            }
        }
    }
    fire(type,args){
        if(!this._message[type]){
            return ;
        }else{
            for(let i of this._message[type]){
                i.call(this.args)
                // this._message[type][i].call(this,args)
            }
        }
    }
}

function Student(state){}
var Student = class{
    constructor(state){
        this.state = state
        this.say = ()=>{console.log(`${this.state}回答问题`)}
    }
       answer(question){
        observer.regist(question,this.say)
    }
    sleep(question){
        observer.cancel(question,this.say)
    }
}
var observer = new Observer()
// 监听问题

var Teacher = class{}
Teacher.prototype.ask = function(question){
    observer.fire(question)
}

var student1 = new Student('1')
var student2 = new Student('2')
var student3 = new Student('3')

student1.answer('问题1')
student1.answer('问题2')
student1.answer('问题3')
student2.answer('问题1')
student2.answer('问题2')
student3.answer('问题1')

student3.sleep('问题1')
var teacher = new Teacher()
teacher.ask('问题1')
teacher.ask('问题2')
teacher.ask('问题3')