zoukankan      html  css  js  c++  java
  • 设计模式

    设计模式有

    工厂模式:创造多个相同的属性,方法的对象的函数。

    function factory(engie, color,run) {

      this.engie = engie;

      this.color = color;

      this.run = run

    }

    var carA = new factory("一","red" ,function a(){})

    var carB = new factory("一ww","red" ,function b(){})

    单例模式

    代理模式分成两个部分,一个部分是本体,即为你想要实现的功能;另一部分为代理,代理可以代替本体做一些处理。

    代理模式预加载图片
    var myImage = (function () {// 本体对象
            var imgNode = document.createElement('img');
            document.getElementById('loadImg').appendChild(imgNode);
            return {
                setSrc: function (src) {
                    imgNode.src = src;
                }
            }
    })();
     
    var proxyImage = (function () {// 代理对象
            var img = new Image();
            img.onload = function () {
                myImage.setSrc(this.src);
            }
            return {
                setSrc: function (src) {
                    myImage.setSrc('loading.gif');
                    img.src = src;
                }
            }
    })();
    proxyImage.setSrc('http://pic39.photophoto.cn/20160411/1155116845138548_b.jpg');
     
    通过proxyImage间接地访问myImage,代理对象proxyImage控制了客户对myImage的访问,
    并且在此过程中加入一些额外的操作,比如在真正的图片加载好之前,
    先把imgNode的src设置为一张本地的loading图片。
     
    策略模式
    策略模式
     
    策略模式的定义是:定义一系列的算法,把它们一个个封装起来,通过传参的方式相互替换并且使它们可以相互替换。
    一个基于策略模式的程序至少由两部分组成:
    第一个部分是一组策略类,策略类封装了具体的算法,并负责具体的计算过程;
    第二个部分是环境类Context,Context接受客户的请求,随后把请求委托给某个策略类。
    '算法':各种业务规则
     
    demo1:计算奖金,基于传统面向对象语言的模仿
    var performanceA = function () {}; // 策略类
    performanceA.prototype.calculate = function (salary) {
        return salary * 8;
    }
    var performanceB = function () {}; // 策略类
    performanceB.prototype.calculate = function (salary) {
        return salary * 5;
    }
    var performanceC = function () {}; // 策略类
    performanceC.prototype.calculate = function (salary) {
        return salary * 3;
    }
     
    var Bonus = function () { // 奖金类(环境类)
        this.salary = null; // 原始工资
        this.strategy = null; // 绩效等级对应的策略对象
    }
    Bonus.prototype.setSalary = function (salary) {
        this.salary = salary; // 设置原始工资
    }
    Bonus.prototype.setStrategy = function (strategy) {
        this.strategy = strategy; // 设置绩效等级对应的策略对象
    }
    Bonus.prototype.getBonus = function () { // 取得奖金数额
        // 把计算奖金的操作委托给对应的策略对象
        return this.strategy.calculate(this.salary);
    }
     
    var bonus = new Bonus(); // 奖金类实例
    bonus.setSalary(10000); // 设置原始工资
    bonus.setStrategy(new performanceA()); //设置策略对象
    console.log(bonus.getBonus()); // 80000
    bonus.setStrategy(new performanceB()); //设置策略对象
    console.log(bonus.getBonus()); // 50000
     
    demo2:JavaScript版本的策略模式
    var strategies = { //策略对象,封装算法
        'A': function (salary) {
            return salary * 8;
        },
        'B': function (salary) {
            return salary * 5;
        },
        'C': function (salary) {
            return salary * 3;
        }
    }
    var calculateBonus = function (level, salary) { //环境类,接受客户的请求
        // 把计算奖金的操作委托给对应的策略对象
        return strategies[level](salary);
    }
    console.log(calculateBonus('A', 10000)); //80000
    console.log(calculateBonus('B', 10000)); //50000
     
     
    发布-订阅模式
     
    发布-订阅模式又叫观察者模式,它定义对象间的一种 一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。在JavaScript开发中,我们一般用事件模型来替代传统的发布-订阅模式。最常用且最简单的发布-订阅模式:DOM事件
    document.body.addEventListener('click', function () {
        alert('消息');
    }, false);
    订阅document.body上的click事件,当body节点被点击时,body节点便会向订阅者发布这个消息
     
    发布-订阅模式的一个应用场景:售楼处(发布者)给意愿购房者(订阅者)发消息
    var saleOffice = { //售楼处
        clientList: {}, //缓存列表,存放订阅者的回调函数
        addlisten: function (key,fn) { //添加订阅者
            if (!this.clientList[key]) { //未订阅过此类消息,创建一个缓存列表
                this.clientList[key] = [];
            }
            this.clientList[key].push(fn); //订阅的消息添加进消息缓存列表
        },
        trigger: function (key,msg) { //发布消息方法
            var fnArr = this.clientList[key]; //取出该消息对应的回调函数集合
            if (!fnArr || fnArr.length == 0) {
                return false; // 如果未订阅该消息,则返回
            }
            for (var i = 0; i < fnArr.length; i++) {
                fnArr[i](msg); //执行所有回调函数
            }
        }
    }
    saleOffice.addlisten('houseTypeA',function (msg) { //订阅消息
        console.log('尊敬的客户,您关注房源信息为:' + msg);
    });
    saleOffice.addlisten('houseTypeB',function (msg) { //订阅消息
        console.log('尊敬的客户,您关注房源信息为:' + msg);
    });
    saleOffice.trigger('houseTypeA','户型A,12000/m,建筑面积90平米。'); //发布消息
    saleOffice.trigger('houseTypeB','户型B,12800/m,建筑面积120平米。'); //发布消息
     
     
    案例:网站登录
    假如一个商城网站项目有header头部、nav导航、消息列表、购物车、地址管理等模块,这些模块的渲染有一个共同的前提条件,就是必须先用ajax异步请求获取用户的登录信息。如果它们和用户信息模块产生了强耦合,比如下面这样的形式:
    $.ajax({
        type: 'post',
        url: 'https://www.baidu.com/',
        data: 'user=xiaocuo&pass=123456',
        dataType: 'json',
        success: function (data) {
            header.setAvatar(data.avatar); // 设置头部头像
            nav.setAvatar(data.avatar); // 设置导航头像
            address.refresh(); // 刷新收货地址列表
            message.refresh(); // 刷新消息列表
            cart.refresh(); // 刷新购物车列表
            // ......
        }
    })
    我们必须知道header模块设置头像的方法叫setAvatar,刷新购物车列表的方法叫refresh,各种新增模块的方法...等等,我们会越来越疲于应付这些突如其来的业务要求!
     
    用发布-订阅模式重构之后,对用户信息感兴趣的业务模块将自行订阅登录成功的消息事件
    var loginEvent = { //登录成功的消息事件
        clientList: {}, //缓存列表,存放订阅者的回调函数
        addlisten: function (key,fn) { //添加订阅者
            if (!this.clientList[key]) { //未订阅过此类消息,创建一个缓存列表
                this.clientList[key] = [];
            }
            this.clientList[key].push(fn); //订阅的消息添加进消息缓存列表
        },
        trigger: function (key,msg) { //发布消息方法
            var fnArr = this.clientList[key]; //取出该消息对应的回调函数集合
            if (!fnArr || fnArr.length == 0) {
                return false; // 如果未订阅该消息,则返回
            }
            for (var i = 0; i < fnArr.length; i++) {
                fnArr[i](msg); //执行所有回调函数
            }
        }
    }
     
    $.ajax({
        type: 'post',
        url: 'https://www.baidu.com/',
        data: 'user=xiaocuo&pass=123456',
        dataType: 'json',
        success: function (data) {
            loginEvent.trigger('loginSucc', data); // 发布登录成功消息
        }
    })
     
    各个业务模块自己监听登录成功的消息:
    var header = (function () { // 头部模块
        loginEvent.addlisten('loginSucc', function (data) { //订阅登录成功的消息
            header.setAvatar(data.avatar);
        });
        return {
            setAvatar: function (data) {
                console.log('设置头部模块头像');
            }
        }
    })();
    var nav = (function () { // 导航模块
        loginEvent.addlisten('loginSucc', function (data) { //订阅登录成功的消息
            nav.setAvatar(data.avatar);
        });
        return {
            setAvatar: function (data) {
                console.log('设置导航模块头像');
            }
        }
    })();
    var address = (function () { // 地址模块
        loginEvent.addlisten('loginSucc', function (obj) { //订阅登录成功的消息
            address.refresh(obj);
        });
        return {
            refresh: function (data) {
                console.log('刷新收货地址列表');
            }
        }
    })();
    // ......
     
     
  • 相关阅读:
    在DevExpress程序中使用SplashScreenManager控件实现启动闪屏和等待信息窗口
    使用Setup Factory安装包制作工具制作安装包
    PostgreSQL介绍以及如何开发框架中使用PostgreSQL数据库
    在DevExpress中使用CameraControl控件进行摄像头图像采集
    读取数据库信息构建视图字段的备注信息,方便程序代码生成
    混合框架中Oracle数据库的还原处理操作
    使用图片视频展示插件blueimp Gallery改造网站的视频图片展示
    .NET缓存框架CacheManager在混合式开发框架中的应用(1)-CacheManager的介绍和使用
    在Winform界面菜单中实现动态增加【最近使用的文件】菜单项
    文字处理控件TX Text Control的使用
  • 原文地址:https://www.cnblogs.com/xiaoniaohhl/p/14495298.html
Copyright © 2011-2022 走看看