资讯专栏INFORMATION COLUMN

实用模式之中介者模式

AlexTuan / 2607人阅读

摘要:好,师傅我们要学习帝吧人民,进能打,退能刷淘宝。恩,大致过程就是这样,我们使用中介者模式想一想。首先,数据需要放在中介者模式内,用户的一切操作,都会传递给中介者模式,由他来选择是哪一个部分发生改变。

俗话说,一个模式三个坑。 中介者模式应该算最坑的一个模式,坑不在于他的原理。而在于他的名字和其他模式的使用,真尼玛像。首先,“中介者“ 好像是一切模式里面都有的一个东西,比如,享元模式中-元对象,订阅发布模式中-全局监听Event... 但是,这个模式偏偏又叫做中介者模式(哎,曾经说模式的时候,感觉什么都是中介者模式)。

所以,这里我们首先要攻克的难关就是,中介者模式的features。

中介者模式

首先,我们需要回忆一下使用订阅发布模式中,是怎样一个场景

恩,中间需要有一个连接节点,即,发布者只需要和连接者有关联,而订阅者同样也只需要和连接者有关联。 所以,这个点就是中介者模式最独特的feature. 下图可以清楚的看出,中介者模式的特点。

知道了吧,中介者模式最突出的就是,由中介者来掌管一切,比订阅者中的连接节点的地位好像就是爸爸和儿子的关系。

中介者模式的实现

在发布订阅模式中有着全局对象Event的管理,那中介者模式中的boss应该怎样表达呢?

首先,我们需要说明一下,中介者模式主要的应用场景是什么。

有大量相互关联的对象

每个对象都能改变状态

你写的代码比较烂

差不多中介者模式能够解决以上的问题。

徒儿,给师傅去要个栗子来。
好的,师傅!!!

栗子来了:

大家好,(我假装我是一名学霸) 同学们可能经常去的地方,应该就是图书馆了,经常会去图书管理处借一些书来看,比如: 藏地密码,阿弥陀佛么么哒...等等。我们凭借着尽职的图书馆阿姨,往往可以借到我们想要的书本。如果已经被借走了,还可以在阿姨那里登记,并且如果书还回来的,会通知你过来取。

恩,总结一下:

图书馆阿姨其实就是一个中介者,我们找书,都是通过图书管理处询问,然后他们负责给我们查询。 如果没有这个管理处的话,就像我们平时一样,在群里问问,"大家有xxx书吗?能借我看两天吗?"。当然,这样往往会石沉大海。

我们用代码模拟一下:

//我们先假设图书管理系统只有借和还的功能
//个人
function Person(name){
    this.name = name;
}
Person.prototype.lend = function(bookName){
    Manager.assign("lend",this,bookName);
}
Person.prototype.back = function(bookName){
    Manager.assign("back",this,bookName);
}
//创建一个工厂模式
var peopleFactory = (function(){
    var people = {};
    return function(name){
        var person = people[name];
        if(person){
            return person;
        }
        person = new Person(name);
        people[name] = person;
        return person;
    }
})();
//中介者,图书管理处
var Manager = (function(){
    var lendList = {},
        stock = {},
        operations = {};
    operations.lend = function(person,bookName){
        var num = stock[bookName];

        if(num===undefined){  //判断是否有书
            console.log("图书馆没有该书");
            return;
        }
        if(num===0){  //书本已经借完
            console.log("该书已经借完");
            return;
        }
        stock[bookName]--;  //将数量减一
        lendList[person.name] = bookName;
        console.log("借阅成功");
    }
    operations.back = function(person,bookName){
        var bookName = lendList[person.name];  //返回借书人借的书名
        if(bookName === null){
            throw "该人,并没有借书";
        }
        stock[bookName]++;  //还书
        lendList[person.name] = null;  //将借书人的清空
    }
    operations.addStock = function(){  //初始库存,addStock({bookName:jimmy,num:2})
        for(var i = 0,book;book = arguments[i++];){
            stock[book.bookName] = book.num;
        }
    }
    var assign = function(){
        var order = Array.prototype.shift.call(arguments);
        operations[order].apply(this,arguments);
    }
    return {
        assign
    }
})();
Manager.assign("addStock",{bookName:"藏地密码",num:1},{bookName:"阿弥陀佛么么哒",num:3});
var xiaoMing = peopleFactory("xiaoMing");
var jimmy = peopleFactory("jimmy");
var hanMM = peopleFactory("hanMM");
xiaoMing.lend("藏地密码");
jimmy.lend("藏地密码");
//还书的过程
xiaoMing.back("藏地秘密");
jimmy.lend("藏地密码");  //终于借成功了

以上是一个简单的中介者模式的缩影,要始终记着那张图代表的内涵,中介者模式是不需要在将请求传递出去的(或者说,情感上没有传递出去)。

中介者模式的现实意义

上面意淫了一个图书管理处(实话说,没有卵用). 我们来个真的。

徒儿,给师傅找个栗子。
好,师傅!!!

我们要学习帝吧人民,进能打td,退能刷淘宝。 我们这里不说淘宝的事,但说一个电子商务的事。 现在Mooc这么火,各种线上课程也是numberous。我也上过。 一个线上的课程需要购买,购买的流程基本上就是,选择你想要的课程,然后,选择你要上课的人数(你是一个妈妈,你可以给你两个孩纸各买一个ID),如果上课人数未满的话,恭喜,你在家等开课就over了。如果课程满的话,你要么等下一期,要么,直接找另外一门课。

如果使用,面向过程的思维写的话,我相信这个,不是一般的复杂。

所以,我们使用面向对象的思维重构一下。

首先,我们得拿到课程的数据,比如,课程名,已经报的课程人数,课程价格等。当我们选择一个课程的时候,界面上肯定需要作出相应的处理,比如,渲染课程价格,剩余人数。但我们添加购买人数的时候,如果未超出,则可以购买,如果超出,则需要将购买的按钮改为不可选中状态。

恩,大致过程就是这样,我们使用中介者模式想一想。

首先,数据需要放在中介者模式内,用户的一切操作,都会传递给中介者模式,由他来选择是哪一个html部分发生改变。

好,我们用代码实现以下。

课程购买

上面是整个逻辑和页面,这里我主要针对js说明一下。

(function() {
    console.dir($(".courses"))
    bind($(".courses"), function(e) { //课程内容改变时
        mediator.command(e.target);
    }, "change");
    bind($(".num"), function(e) { //报名人数改变时
        mediator.command(e.target);
    }, "keyup");

    bind($(".buy"), function(e) { //绑定够买函数
        mediator.command(e.target);
    }, "click");

    var utils = (function() { //工具函数
        var change = function(ele, val) { //改变内容
            ele.innerHTML = val;
        }
        return {
            change
        };
    })();



    var mediator = (function() { //中介者
        var price = $(".price"), //课程价格
            remainder = $(".remainder"), //剩余人数
            num = $(".num"), //购买人数
            buyBtn = $(".buy"), //购买btn
            course;
        var changePR = function(courseName) { //改变价格和人数
            course = data[courseName];
            console.log(course);
            utils.change(price, course.price); //改变价格
            utils.change(remainder, course.remainder); //改变人数
        }
        var prohitBtn = (function() { //改变购买btn状态
            var use = ``,
                ban = ``,
                status = true;
            return function(flag) {
                if (status === flag) { //如果状态不变,则不改变内容
                    return;
                }
                if (flag === true) { //可以购买
                    buyBtn.innerHTML = use;
                    status = true;
                } else { //禁止购买
                    buyBtn.innerHTML = ban;
                    status = false;
                }
            }
        })();
        var detect = function() { //检测购买输入的内容
                var number = Number(num.value.trim());
                if (!course) {
                    alert("请先选择课程");
                    return;
                }
                if (number > course.remainder) {
                    prohitBtn(false); //不能够买
                }  else {
                    prohitBtn(true); //可以够买
                }
            }
            //当课程类改变时,触发改变名额,价格以及根据购买人数改变购买Btn的状态
        var coursesChange = function(courseName) {
            //改变价格和人数
            changePR(courseName);
            //根据input框的值,改变btn的状态
            detect();
        }
        var detectBuy = function() {
            var number = Number(num.value.trim());
            if (number === null || number == 0) {
                alert("请先输入购买数量~");
            } else {
                alert("购买成功");
            }
        }
        var command = function(target) {
            var classList = target.classList;
            if (classList.contains("courses")) {
                console.dir(target.value);
                var val = target.value;
                //执行
                coursesChange(val);
            } else if (classList.contains("num")) {
                var val =target.value.trim(),
                    reg = /d+/;
                if (!reg.test(val)) {
                    alert("输入内容只能为数字");
                    return;
                }
                //执行
                detect();
            } else if(classList.contains("shoppingBtn")){
                detectBuy();
            }
        }
        return {
            command
        }
    })();
})();

可以从上面的代码看出,比较清晰的将沟壑关系解除,上面的中介者模式中也会用到代理模式等其他相关的知识。当然,这段代码并不是特别好,关键在于处理的逻辑较多,有大量的if判断语句,所以也希望读者,可以使用以前所学的js模式进行重构,我相信到时候你的代码整洁程度一定远优于鄙人写的代码。

浅说中介者模式

其实,中介者模式是我最喜欢使用的模式之一,因为他好写易上手。但是缺点也是显而易见的,就是,你会在程序中增加一个巨大的对象,而你的噩梦就是维护这个对象。 中介者里面会包含大量的逻辑,设计较多的节点获取,造成的维护难度也是显而易见的。所以,还是那句话,不要为了模式而模式,这个世界上没有万能的模式,就和没有绝对安全的系统一样。

ending~

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/78527.html

相关文章

  • 2017-09-22 前端日报

    摘要:前端日报精选在中的元素种类及性能优化译异步递归回调译定位一个页面阻塞问题的排查过程前端分享之的使用及单点登录中文视频如何用做好一个大型应用云际个实用技巧众成翻译年一定不要错过的五本编程书籍年前端领域有哪些探索和实践实现一个时光网掘金 2017-09-22 前端日报 精选 JavaScript 在 V8 中的元素种类及性能优化【译】异步递归:回调、Promise、Async[译]HTML...

    xiaochao 评论0 收藏0
  • 设计模式介者模式

    摘要:用中介者模式实现土豆馒头豆包地瓜土豆馒头豆包地瓜土豆馒头输出缺陷使用中介者模式可以很大程度上避免对象之间的相互影响,无论是对于代码的可读性以及逻辑性都可以简化。 中介者模式 我们知道在程序中各个对象之间并不是完全独立的,相互之间是可能存在关系的,并且可能会相互影响的,就像这样。 showImg(https://segmentfault.com/img/bVJ8wK?w=428&h=51...

    shixinzhang 评论0 收藏0
  • “大话”设计模式

    摘要:抽象工厂模式是为了处理对象具有等级结构以及对象族的问题。单例设计模式单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类成为单例类。 导语:设计模式是无数码农前人在实际的生产项目中经过不断的踩坑、爬坑、修坑的经历总结出来的经验教训,经过抽象之后表达成的概念。能够帮助后来的设计者避免重复同样的错误或者弯路。我也抽空整理了一下设计模式,用自己的话总结了一下,自认...

    coordinate35 评论0 收藏0
  • javascript介者模式

    摘要:中介者模式中介者模式对象和对象之间借助第三方中介者进行通信。将就用下这个这个函数充当中介者挑戰成功挑战失败选手选手选手选手挑战成功选手挑战成功选手挑战失败在这段代码中之间没有直接发生关系而是通过另外的对象建立链接姑且将之当成是中介者模式了。 中介者模式 中介者模式: 对象和对象之间借助第三方中介者进行通信。 showImg(https://segmentfault.com/img/bV...

    LucasTwilight 评论0 收藏0
  • 设计模式介者模式

    摘要:中介者模式的应用中介者模式的优点就是减少类间的依赖,将一对多的依赖变成一对一的依赖,降低耦合,符合迪米特法则。中介者模式适用于多个对象之间出现紧密联系,类图成网状结构,使用中介者模式可以梳理为星型结构,有助于理解其关系。 前言 由于最近疯狂加班,博客都停更许久,难过~.~ 中介者模式定义 用一个中介对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使其耦合松散,而且可以...

    jackwang 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<