美文网首页前端小样
JavaScript 设计模式

JavaScript 设计模式

作者: 小淘气_嘻 | 来源:发表于2018-06-29 15:30 被阅读0次

设计模式

  • 可重用、可扩展、可解耦、容易理解
  • 目标是为了代码复用,增加可维护性
  • 原则:
    1. 对扩展开放,对修改关闭
    2. 里氏转换原则:子类继承父类,单独完全可以运行
    3. 依赖倒转原则:引用一个对象,如果这个对象有底层类型,直接引用底层
    4. 接口隔离原则:每个接口应该是一种角色
    5. 合成/聚合复用原则:新的对象应使用一些已有的对象,使之成为新对象的一部分
    6. 迪米特原则: 一个对象应对其他对象有尽可能少得了解

单例模式

  • 一个类只有一个实例

  • 实现方法:先判断实例存在与否,如果存在直接返回,如果不存在就创建了再返回

  • 单例是一个命名空间的提供者

  • 唯一、易阻塞、有序、序列化

    • 数据
    • 执行通道
    • 执行体
  • 多个线程调用单例

  • 作用

    • 模块间通信
    • 系统中某个类的对象只能存在一个
    • 保护自己的属性和方法
  • 注意

    1. this的使用,使用instanceof来验证
    • 闭包容易造成内存泄漏,不需要的赶快干掉
    • new 的成本(继承)

内存泄漏
当一个对象不需要再使用,本该被回收时,受另一个持有它引用的对象影响,导致它不能被回收。
本该被回收的对象不能被回收而停留在堆内存中。
内存泄漏的影响:应用所需的内存超过系统分配的内存限额,内存溢出导致应用Crash

单例模型普通样例: 不同单例在同一命名空间

var demo1= (function(argument){
    var attr1 = function(message){
        this.menling = message;
    };
    var men;
    var obj={
        fun1:function(message){
            if(men){
                men = new attr1(message);
            }
            return men;
        }
    }
    return obj;
})();


var demo2 = {
    fun2 :function(msg){
        var _demo = demo1.fun1(msg);
        alert(_demo);
        _demo = null;    //等待垃圾回收  及时清理存储空间
    }
}

demo2.fun2('didi);

把对应的逻辑封装到对应的区块中,不同命名空间下,减少变量污染

//页面上6个按钮 abcdef
//abc在top命名空间下
//def在banner命名空间下

var top={
    init:function(){ //top的初始化
        this.render();
        this.bind();    
    },
    a:4,  //传递的参数
    render:function(){//把所有DOM元素放进去
        var me = this;
        me.btna = $('#a');
    },
    bind :function(){
        var me = this;
        me.btna.click(function(){
            //业务逻辑
            me.test();
        });
    },
    test:function(){
        a=5;
    }
}
var banner={
    init:function(){ //top的初始化
        this.render();
        this.bind();
    },
    a:4,  //传递的参数 不同命名空间互相保护
    render:function(){//把所有DOM元素放进去
        var me = this;
        me.btna = $('#a');
    },
    bind :function(){
        var me = this;
        me.btna.click(function(){
            //业务逻辑
            me.test();
        });
    },
    test:function(){
        top.a=5;
    }
}

top.init();
banner.init();

构造函数模式 (构建构造函数)

  • 用于创建特定类型的对象

    • 声明了使用对象
    • 接受参数以便第一次创建对象的时候设置对象的成员值
  • 自定义自己的构造函数,并声明自定义类型对象的属性和方法

  • 用来实现实例

    • 用new关键字来调用自定义的构造函数
    • 在构造函数内部,this引用的是新创建的对象
  • 作用
    1. 用于创建特定类型的对象
    • 第一次声明的时候给对方扶着
    • 自己声明构造函数,赋予属性和方法
  • 注意事项
    1. 声明函数的时候处理业务逻辑(只包含特定对象的业务逻辑)
    • 与单例区别,配合单例实现初始化
    • 构造函数大写字母开头
    • 注意new的成本(继承)(公用的方法放在构造函数中)
//js开发写单引号
//js必须通过new来让this指向该对象
//PHP实现构造函数模式,关键字

var AA ={
    zaomen:function(huawen){
    if(!(this instanceof zaomen)){ //instanceof 用于检测this是否是zaomen类的一个实例
        return new zaomen();
    }
    this.suo = '普通',
    this.huawen = huawen || '普通' ,
    this.create = function(){
        return '锁头' +this.suo +'花纹'+this.huawen;
    }   
    }   
}
var BB ={
    zaomen:function(huawen){
    if(!(this instanceof zaomen)){ //instanceof 用于检测this是否是zaomen类的一个实例
        return new zaomen();
    }
    this.suo = '普通',
    this.huawen = huawen || '普通' ,
    this.create = function(){
        return '锁头' +this.suo +'花纹'+this.huawen;
    }   
    }   
}


var xiaozhang = AA.zaomen();
console.log(xiaozhang.create());
    
var xiaoli = new BB.zaomen('绚丽');
console.log('xiaoli' + xiaoli.create());

建造者模式

  • 将一个复杂对象的构建与其表示相分离

    • 同样的构建过程,创建不同的表示
  • 一个指挥者 + 建造者

  • 分步骤构建一个复杂的对象

    • 分步骤 :稳定的
    • 复杂对象的各个部分 : 经常变化
  • 作用:

    1. 分布创建一个复杂的对象
    • 解耦封装过程和具体创建的组件
    • 无需关心组件如何组装
  • 注意事项:

    1. 一定要一个稳定明确的算法逻辑进行支持
    • 加工工艺是暴露
//发送一个请求  白富美
//$.ajax建造者模式,包工头
//工人 完整的工程
$.ajax({
    url:'a.php',
    success:function(){
    }
})

//建造者模式 :按照人、物清晰的逻辑关系来清晰的设计

function Fangzi(){
    this.woshi ='';
    this.keting ='';
    this.chufang = '';
}

function Baogongtou(){
    this.gaifanzi = function(gongren){
        gongren.jian_woshi();
        gongren.jian_keting();
        gongren.jian_chufang();
    }
}

function Gongren(){
    this.jian_woshi = function(){
        console.log('卧室建好了');
    }
    this.jian_keting = function(){
        console.log('客厅建好了');
    }
    this.jian_chufang = function(){
        console.log('厨房建好了');
    }
    this.jiaogong = function(){
            var _fangzi = new Fangzi();
                _fangzi.whoshi ='ok';
                _fangzi.keting ='ok';
                _fangzi.chufang = 'ok';
            return _fangzi;
    }
}

var gongren = new Gongren();
var baogongtou = new Baogongtou();
var baogongtou.gaifangzi(gongren);
var myfangzi = gongren.jiaogong();
console.log(myfangzi);

工厂模式

  • 定义一个类

  • 用于创建对象的接口,这个接口由子类决定实例化哪一个类

    • 讲一个类的实例化延迟到了子类
    • 子类可以重写接口方法:以便创建的时候指定自己的对象类型(抽象工厂)
  • 创建对象的流程赋值的时候:依赖于很多设置文件

  • 让子类定义需要创建的对象类型

  • 作用

    • 对象的构建十分复杂
    • 需要依赖具体的环境创建不同的实例
    • 处理大量具有相同属性的小对象
  • 注意事项

    • 不能滥用工程,有时会增加复杂度
var gongchang = {};
gongchang.chanyifu = function(){
    this.gongren = 50;
    alert('我们的底线' +this.gongren);
}
gongchang.chanxie = function(){
    alert('产鞋子');
}

gongchang.yunshu = function(){
    alert('运输');
}

gongchang.changzhang = function(para){
    //js用了构造函数模式 以及 单例模式
    return new gongchang[para]();
}

var me = gongchang.changzhang('changyifu');
alert(me.gongren);

让一个工厂分成几个部门,每个部门干自己的事儿 调用时只需要找到这个工厂的这个部分就可以

//简单工厂模式
var XMLHttpFactory = function(){
    
}
XMLHttpFactory.createXMLHttp = function(){
    var XMLHttp = null;
    if(window.XMLHttpRequest){
        XMLHttp = new XMLHttpRequest();
    }elseif(window.ActiveXobject{
        XMLHttp = new ActiveXObject('Microsoft.XMLHttp');
    }
    return XMLHttp;
}

var AjaxHander = function(){
    var XMLHttp = XMLHttpFactory.createXMLHttp();
}

抽象工厂是给你个tag,让你知道这个是什么功能,但是你需要重构丰富他的内容才能使用

//抽象工厂 只留一个,但不做具体的事儿
var XMLHttpFactory = function(){
    
}

XMLHttoFactory.prototype = {
//抛出错误,不能被实例化,只能用来派生子类
    createFactory:function(){
        throw new Error('This is an abstract class');
    }
}
//派生子类

var XHRHandler = function(){
    XMLHttpFactory.call(this);
}
//this发生变化

XHRHandler.prototype = new XMLHttpFactory();
XHRHandler.prototype.constructor = XHRHandler;

XHRHandler.prototype.createFactory = function(){
    var XMLHttp = null;
    if(window.XMLHttpRequest){
        XMLHttp = new XMLHttpRequest();
    }elseif(window.ActiveXobject{
        XMLHttp = new ActiveXObject('Microsoft.XMLHttp');
    }
    return XMLHttp;
}

代理模式(中间件函数进行其他各方,其它各方是相对独立的两个对象)

  • 帮助别人做事

    • GoF~四人帮,合作的一本书成为学习设计模式的圣经。
  • 代理模式Proxy 为其他对象提供一种代理以控制对这个对象的访问。

  • 代理模式使得代理对象控制具体对象的引用

  • 代理几乎可以是任何对象:文件、资源、内存中的对象、或者是一些难以复制的东西

  • 作用

  1. 远程代理(一个对象将不同空间的对象进行局部代理)
  • 虚拟代理(根据需要创建开销很大的对象)

  • 安全代理(控制真实对象的访问权限)

  • 智能指引(调用对象代理处理另外一些事情如垃圾回收机制)

  • 注意:

  1. 不能滥用代理
    //代理模式需要有三方

//买家
function maijia(){
    this.name ='小明';
}
//中介卖房
function zhongjie(){}
zhongjie.prototype.maifang = funcrion(){
    new fangdong(new maijia()).maifang('20万');
}
//房东
function fangdong(){
    this.maijianame = maijia.name;
    this.maifang = function(money){
        alert('收到了来自"'+this.maijianame+'"的'+money+'人民币');
    }
}
(new zhongjie).maifang();

命令模式 (传参)

  • 对方法调用进行参数化处理和传送

    • 经过处理过的方法调用可以在任何需要的时候执行
  • 将函数的调用、请求、操作封装成一个单一的对象,然后对这个对象进行一系列的处理

  • 用来消除调用操作的对象和实现操作的对象之间的耦合

  • 作用

  1. 将函数的封装、请求、调用结合为一体
  • 调用具体的函数来解耦命令对象与接收对象

  • 提高程序模块化的灵活性

  • 注意事项

  1. 不需要接口一致,直接调用函数就好,以免造成浪费
var lian ={};
lian.paobin = function(pao_num){
    alert(pao_num +'炮'+'开始战斗');
}
lian.bubin=function(bubing_num){
    alert(bubing_num +'人'+'开始战斗');
}
lian.lianzhang = function(mingling){
    lian[mingling.type](mingling.num);
}

//总司令开始发令
lian.lianzhang({
    type:'paobing',
    mum:100
})
lian.lianzhang({
    type:'bubing',
    num:500
})

相关文章

网友评论

    本文标题:JavaScript 设计模式

    本文链接:https://www.haomeiwen.com/subject/fctayftx.html