js设计模式五大类总结

// 第一大类、创建型设计模式==一类处理对象创建的设计模式

{
    // a、简单工厂模式(又称:静态工厂方法)
    function creatObj(name, time, type) {
        var o = {};
        o.name = name;
        o.time = time;
        o.type = type;
        o.getName = function () {
            console.log(this, name);
        }
        //返回新对象
        return o;
    }

    // b、安全的工厂方法(增加判断instanceof)

    var factory = function (type, content) {
        if (this instanceof Factory) {
            var o = new this[type](content);
            return o;
        }
    };
    //工厂原型中设置创建所有类型数据对象的基类
    var Factory = function () { };
    Factory.prototype = {
        java: function (content) { },
        php: function (content) { },
        ui: function (content) { }
    }

    // c、抽象工厂模式 (通过对类的工厂抽象使其业务对产品类簇的创建,而不只是一类产品的实例)(抽象类)
    var Car = function () { };
    Car.prototype = {
        getPrice: function () {
            console.log("抽象方法不能调用!");
        },
        getSpeed: function () {
            console.log("抽象方法不能调用!");
        }
    }
    var s = new Car();
    s.getPrice();

    //抽象工厂模式
    var VehicleFactory = function (subType, superType) {
        //判断抽线工厂中是否有该抽象类
        if (typeof VehicleFactory[subType] === 'function') {
            //缓存类
            function F() { }
            //集成父类属性和方法
            F.prototype = new VehicleFactory[subType];
            //将子类constructor指向子类
            subType.constructor = subType;
            //子类的原型集成“父类”
            subType.prototype = new F();
        } else {
            //不存在该抽象类
            throw new Error("未创建该抽象类");
        }
    }

    //小汽车抽象类
    VehicleFactory.Car = function () {
        this.type = "car";
    }
    VehicleFactory.Car.prototype = {
        getPrice: function () {
            console.log("小汽车方法!");
        },
        getSpeed: function () {
            console.log("小汽车方法!");
        }
    }

    //公交车抽象类
    VehicleFactory.Bus = function () {
        this.type = "bus";
    }
    VehicleFactory.Bus.prototype = {
        getPrice: function () {
            console.log("公交车方法!");
        },
        getSpeed: function () {
            console.log("公交车方法!");
        }
    }

    //货车抽象类
    VehicleFactory.Truck = function () {
        this.type = "truck";
    }
    VehicleFactory.Truck.prototype = {
        getPrice: function () {
            console.log("货车方法!");
        },
        getSpeed: function () {
            console.log("货车方法!");
        }
    }
    //宝马汽车类
    var BWM = function (price, speed) {
        this.price = peice;
        this.speed = speed;
    };
    // 抽象工厂对Car抽象类实现继承
    VehicleFactory(BWM, "Car");//判断是否含有此类
    //子类重写父类方法
    BWM.prototype.getPrice = function () {
        return this.price;
    }

    //大众汽车类
    var DZ = function (price, speed) {
        this.price = peice;
        this.speed = speed;
    };
    // 抽象工厂对Car抽象类实现继承
    VehicleFactory(DZ, "Car");//判断是否含有此类
    DZ.prototype.getPrice = function () {
        return this.price;
    }

    // PS:通过抽象工厂可以知道是哪个抽象类的继承


    //工厂模式关注的是创建对象的最终实例
    // d、建造者模式(将一个复杂对象的构架层和表现层分离,同样的构建过程可以采用不通展现)(关注船舰对象的细节问题)
    /**
     * 应聘者建造者
     * 参数name : 姓名
     * 参数work :期望职位
     */
    var Named = function (name) { };
    var Work = function (work) { };
    Named.prototype.getName = function () { };
    work.prototype.getWork = function () { };

    var Person = function (name, work) {
        //创建应聘者缓存对象
        var _person = new Human();
        //创建应聘者姓名对象
        _person.name = new Named(name);
        //创建应聘者期望值为对象
        _person.work = new Work(work);
        //返回创建的应聘者
        return _person;
    }

    // e、原型模式(用原型实例指向创建对象的类,使得新创建的对象的类共享原型对象的属性以及方法)
    //图片轮播
    var LoopUmages = function (imgArr, container) {
        this.imagesArray = imgArr;       //轮播图片数组
        this.container = container;      //轮播图片容器
        this.createImage = function () { }; //创建轮播图片
        this.changeImage = function () { }; //切换下一张图片
    }
    // 最优方式
    var LoopUmages = function (imgArr, container) {
        this.imagesArray = imgArr;       //轮播图片数组
        this.container = container;      //轮播图片容器
    }
    LoopUmages.prototype = {
        createImage: function () { }; //创建轮播图片
        changeImage: function () { }; //切换下一张图片
    }
    // 实现不同效果而继承后重写实例方法
    //上下滑动继承切换类
    var SlideLoopImg = function (imgArr, container) {
        //构造函数继承图片轮播类
        LoopImages.call(this, imgArr, container);
        //重写继承的切换下一张图片的方法
        this.changeImage = function () {
            console.log('SlideLoopImage changeImage function');
        }
    }
    //渐隐继承切换类
    var FadeLoopImg = function (imgArr, container, arrow) {
        //构造函数继承图片轮播类
        LoopImages.call(this, imgArr, container);
        //切换箭头私有变量
        this.arrow = arrow;
        //重写继承的切换下一张图片的方法
        this.changeImage = function () {
            console.log('FadeLoopImg changeImage function');
        }
    }

    // 属性复制实现对象创建,减少new的使用
    function prototypeExtend() {
        var F = function () { },
            args = arguments,
            i = 0,
            len = args.length;
        for (; i < len; i++) {
            for (var j in args[i]) {
                F.prototype[j] = args[i][j];
            }
        }
        return new F();
    }


    // f、单例模式(只允许实例化一次的对象类,也称为单体模式)
    //就是为所定义的方法提供一个命名空间(namespace)  如  jqury
    var Conf = (function () {
        //私有变量  静态变量   习惯大写
        var conf = {
            MAX_NUM: 100,
            MIN_NUM: 1,
            COUNT: 1000
        }
        //返回取值器对象
        return {
            //取值器的方法
            get: function (name) {
                return conf[name] ? conf[name] : null;
            }
        }
    })()

    //惰性单例模式
    var LazySingle = (function () {
        //单体实例引用
        var _instance = null;
        function Single() {
            //定义私有属性和方法
            return {
                publicMethod: function () { },
                publicProperty: "1.0"
            }
        }
        //获取单例对象接口
        return function () {
            //如果未创建单利将创建
            if (!_instance) {
                _instance = Single();
            }
            //返回单例
            return _instance;
        }
    })()
}

第二大类、结构型设计模式(将类和对象组合成更复杂的结构)

{
    // a、外观模式(为一组复杂的子系统接口提供一个更高级的统一接口)
    //添加事件的外观模式实现
    function addEvent(dom, type, fn) {
        if (dom.addEventListener) {
            dom.addEventListener(type, fn, false);//多数浏览器
        } else if (dom.attachEvent) {
            dom.attachEvent("on" + type, fn);//低版本ie
        } else {
            dom['on' + type] = fn;//支持on的
        }
    }

    //获取事件对象
    var getEvent = function (event) {
        //标准浏览器返回event    IE返回window.event
        return event || window.event;
    };
    //获取元素
    var getTarget = function (event) {
        var event = getEvent(event);
        //标注浏览器下event.target,IE下event.srcElement
        return event.event || event.srcElement;
    }
    //阻止默认行为
    var perventDefault = function (event) {
        var event = getEvent(event);
        if (event.preventDefault) {
            //标准浏览器
            event.preventDefault();
        } else {
            //IE览器
            event.returnValue = false;
        }
    };

    // b、适配器模式(将一个类的接口转化成另外一个接口,已满足需求)
    // 传参使用
    var parmas = {
        name: "name",
        age: "age",
        sex: "sex"
    }

    // c、代理模式(一个对象不能直接引用另一个对象,所以需要通过代理在这两个对象之间起到中介的作用)
    // 图片的src实现统计代理(单向  无返回)
    //统计代理
    var Count = (function () {
        //缓存图片(参考备忘录模式)
        var _img = new Image();
        //返回统计函数
        return function (param) {
            //统计请求字符串
            var str = "http://www.count.cim/a.gif";
            //拼接请求字符串
            for (var i = 0 in param) {
                str += i + "=" + param[i];
            }
            //发送统计数据
            _img.src = str;
        }
    })();
    //测试用例
    Count({ num: 10 });

    //scrupt标签代理模式(请求只是单份数据,需要src的url加上标识  服务区获取后保留一份)
    //也就是callback的实现(jsonp方案)
    //图片预加载也成为虚拟代理模式

    // d、装饰者模式(在不改变原对象的基础上,对其拓展属性和方法以满足客户需求)
    //装饰者
    var decorator = function (input, fn) {
        //获取事件源
        var input = document.getElementById(input);
        //若事件源已绑定事件
        if (typeof input.onclick === "function") {
            //缓存事件源原有回调函数
            var oldClickFn = input.onclick;
            //为事件源定义新的事件
            input.onclick = function () {
                //事件源原有回调函数
                oldClickFn();
                //执行新增回调函数
                fn();
            }
        } else {
            //事件源未绑定事件,直接添加新增事件即可
            input.onclick = fn;
        }
        //做其他事情

    }
    // PS:与适配器模式的区别是:适配器需要了解原有方法的实现细节,装饰着模式不需要,原有方法原封不动的调用。

    // e、桥接模式(解耦)
    //抽象
    function changeColor(dom, color, bg) {
        //设置元素字体颜色
        dom.style.color = color;
        //设置元素背景颜色
        dom.style.background = bg;
    }

    var spans = document.getElementByTagName("span");
    spans[0].onmouseover = function () {
        changeColor(this, "red", "#add");
    }
    // changeColor方法中的dom实质上是事件回调函数中的this,我们相解除他们之间的耦合,就需要一个桥接方法-----匿名回调函数。
    // 通过这个函数,获取到this传递到changeColor函数中,即可实现。
    //桥接模式就是先抽象提取公共部分,然后将实现与抽象通过桥接方法链接在一起
    spans[0].onmouseover = function () {
        changeColor(this.getElementByTagName("strong")[0], "red", "#add");
    }

    // f、组合模式(使得单个对象和组合对象的使用具有一致性)(难点==============)
    var News = function () {
        //子组件容器
        this.children = [];
        //当前组件元素
        this.element = null;
    }
    News.prototype = {
        init: function () {
            throw new Error("请重写你得方法!");
        },
        add: function () {
            throw new Error("请重写你得方法!");
        },
        getElement: function () {
            throw new Error("请重写你得方法!");
        }
    }
    //容器类构造函数
    var Container = function (id, parent) {
        //构造函数继承父类
        News.call(this);
        //模块id
        this.id = id;
        //模块的父容器
        this.parent = parent;
        //构建方法
        this.init();
    }
    //寄生式继承父类原型方法
    inheritPrototype(Container, News);
    //构建方法
    Container.prototype.init = function () {
        this.element = document.createElement("ul");
        this.element.id = this.id;
        this.element.className = "new-container";
    };
    //添加子元素方法
    Container.prototype.add = function (child) {
        //在子元素容器中插入子元素
        this.children.push(child);
        //插入当前组件元素树中
        this.element.appendChild(child.getElement());
        return this;
    }
    //获取当前元素的方法
    Container.prototype.getElement = function () {
        return this.element;
    }
    //显示方法
    Container.prototype.show = function () {
        this.parent.appendChild(this.element);
    }
    // g、享元模式(运用共享技术有效的支持大量的细粒度的对象)
    // 分页模式应用
    // 提取公用部分  继承享用  较少内存消耗
}

第三大类、行为型设计模式(将对象之间职责划分或算法抽象)

// a、模板方法模式
// 父类中实现的算法骨架,延迟到子类中实现具体步骤,可以在子类中重新定义算法中某些实现步骤
// 弹框实现
//继承类也可以作为模板类

// b、观察者模式(发布订阅者模式)(重点)(定义了一种依赖关系,解决了主体对象与观察者之间功能的耦合)
//将观察者放在闭包中,当页面加载就立即执行
var Observer =(function(){
    //防止消息队列暴漏而被篡改故将消息容器作为静态私有变量保存。
    var _messages = {};
    return {
        //注册信息接口(将订阅者注册的消息推入到消息队列)
        regist:function(type,fn){
            //如果此消息不存在应该创建一个该消息类型
            if(typeof _message[type] === "undefined"){
                //将动作推入到消息对应的动作执行队列中
                _messages[type] = [fn];
            }else{//如果消息存在
                //将动作推入到消息对应的动作执行队列中
                _messages[type].push(fn);
            }
        },
        //发布信息接口
        fire:function(){
            //如果该消息没有被注册,则返回
            if(!_messages[type]){
                return;
            }
            //定义消息信息
            var events = {
                type:type,         //消息类型
                args:args || {}    //消息携带数据
            },
            i=0,
            len = _messages[type].length;   //消息动作的长度
            //遍历消息动作
            for(;i<len;i++){
                //一次执行注册的消息对应的动作序列
                _messages[type][i].call(this,events);
            }
        },
        //移除信息接口
        remove:function(){
            //如果消息动作队列存在
            if(_messages[type] instanceof Array){
                //从最后一个消息动作遍历
                var i = _messages[type].length-1;
                for(;i>=len;i--){
                    //如果存在该动作消息动作序列中移除相应动作
                    _messages[type][i] === fn && _messages[type].splice(i,1);
                }
            }
        }
    }
})();
//使用
Observer.regist("test",function(e){
    console.log(e.type,e.args.msg);
})

Observer.fire("test",{msg:"传递参数"})

// c、状态模式(当对象内部状态发生改变时,会导致行为改变)(减少判断分支)
//d、策略模式:(将定义的一组算法封装起来,使其之间可以替换。封装的算法具有一定独立性,不会随客户端变化而变化)(减少判断分支)
//e、职责链模式:(解决请求发送者和接收者之间的耦合)
//f、命令模式:(将请求和实现解耦并封装成独立对象)

//g、访问者模式(针对对象结构中的元素,定义在不改变该对象的前提下访问结构中元素的新方法)(精髓就是call和apply)
function bindIEEvent(dom,type,fn,data){
    var data = data || {};
    dom.attachEvent("on"+type,function(e){
        fn.call(dom,e,data);
    })
}
// PS:Object.prototype.toString.call来判断返回的数据类型   把对象转成类数组  可以使用数组方法了
//h、中介者模式(通过中介者对象封装一系列对象之间的交互)类似发布订阅模式
//i、备忘录模式(缓存分页数据)
//j、迭代器模式()
//k、解释器模式()

第四大类、技巧型设计模式(将对象之间职责划分或算法抽象)

//a、链模式(jq  return  this)
//b、委托模式(多个对象接收并处理同一请求,将他们委托给另一对象统一处理请求)(优化页面的事件绑定)

第五大类、架构型设计模式(将对象之间职责划分或算法抽象)

// a、同步模块模式(分而治之  易于管理代码)
// b、异步模块模式
// c、widget模式
// d、MVC模式
// e、MVP模式
// f、MVVM模式

*欢迎star本人github:https://github.com/flyku*

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值