提高可扩展性(下)

应对需求上的变更

  1. 观察者模式
    目的:减少对象见的耦合,来提高扩展性
    应用场景:当两个模块直接沟通会增加他们的耦合性时

2.职责链模式
目的:为了避免请求发送者与多个请求处理者耦合在一起,形成一个链条
应用场景:把操作分割成一系列模块,每个模块只处理自己的事情

3.访问者模式
目的:解耦数据结构与数据操作
应用场景:数据结构不希望与操作有关联

基本结构

观察者模式的基本结构

定义一个中转观察者,两个模块之间不直接沟通,而是通过观察者。一般适用于不方便直接沟通,或者异步操作。

function observe(){
    this.message ={};
}
observe.prototype.regist = function(type,fn){
    this.message[type] = fn;
}
observe.prototype.fire = function(type){
    this.message[type]();
}
observe.prototype.remove = function(type,fn){
    this.message[type] = null;
}

职责链模式的基本结构

把要做的事情组织为一条有序的链条,通过在这条链条传递消息来完成功能。适用于不涉及到复杂异步的操作

function mode1(){

}
function mode2(){
    
}
function mode3(){
    
}
_result=mode1(_result);
_result=mode2(_result);
_result=mode3(_result);

访问者模式的基本结构

通过定义一个访问者,代替直接访问对象,来减少两个对象之间的耦合

var data = {};
var handler = function(){

}
handler.prototype.get = function(){

}
var vistor = function(handler,data){
    handler.get(data);
}

应用示例

观察者模式的示例

1.多人合作的问题
需求:现在假设A工程师写了首页模块,然后B工程师写了评论模块,现在要把评论展示在首页

function observe(){
    this.message ={};
}
observe.prototype.regist = function(type,fn){
    this.message[type] = fn;
}
observe.prototype.fire = function(type){
    this.message[type]();
}
observe.prototype.remove = function(type,fn){
    this.message[type] = null;
}

var observeOb = new observe();

function comment(){
    var self = this;
    this.commentList = [
        {
            type:'hot',
            content:'xxx'
        }
    ]
    observeOb.regist('getHot',function(){
        var _arr = [];
        self.commentList.forEach((item) => {
            if(item.type == 'hot'){
                _arr.push(item);
            }
        })
        return _arr;
    })
}
function index(){
    var _arr = observeOb.fire('getHot')
}

2.一个转盘
需求:有一个转盘应用,没转一圈,速度加快

function observe(){
    this.message ={};
}
observe.prototype.regist = function(type,fn){
    this.message[type] = fn;
}
observe.prototype.fire = function(type){
    this.message[type]();
}
observe.prototype.remove = function(type,fn){
    this.message[type] = null;
}

var observeOb = new observe();

//初始化html -> 最终结果选定 -> 运动效果 -> 运动控制
function htmlInit(target){
    for(var i=0;i<9;i++){
        var _div = document.createElement('div');
        _div.innerHTML = i;
        target.appendChild(_div);
        _domArr.push(_div);
    }
}
function getFinal(){
    var _num =  Math.random()*10+40;
    return Math.floor(_num,0);
}
//{moveTime:10,speed:50}
function mover(moveConfig){
    var nowIn = 0;
    var removeNum = 9;
    var timer = setInterval(() => {
        if(nowIn != 0){
            removeNum = nowIn - 1;
        }
        _domArr[removeNum].setAttribute('class','item');
        _domArr[nowIn].setAttribute('class','item item-on');
        nowIn++;
        if(nowIn == moveConfig.moveTime){
            clearInterval(timer);
            if(moveConfig.moveTime == 10){
                observeOb.fire('finish');
            }
        }
    },moveConfig.speed);
}
function moveControll(){
    var final = getFinal();
    var _circle = Math.floor(final/10,0);
    var stipNum = final%10;
    var _speed = 2000;
    var _runCircle=0;
    move({
        moveTime:10,
        speed:_speed
    })
    observeOb.regist('finish',function(){
        var _time=0;
        _speed-=50;
        _runCircle++;
        if(_runCircle<=_circle){
            _time = 10;
        }else{
            _time = stopNum;
        }
        move({
            moveTime:_time,
            speed:_speed
        })
    })
}
htmlInit(document.getElementById('app'));
moveControll();

职责链模式的示例

1.Axios的拦截器
需求:axios拦截器的设计,大家可以看成一个用给职责链的思想去处理请求

function axios(){
    this.interceptors = {
        request:new this.interceptorsManner(),
        response:new this.interceptorsManner(),
    }
}
axios.prototype.request = function(){
    var chain = [dispathRequest,undefined];
    var promise = Promise.resolve(config);
    this.interceptors.request.handlers.forEach((interceptor) => {
        chain.unshift(interceptor.fulfilled,interceptor.rejected);
    })
    this.interceptors.response.handlers.forEach((interceptor) => {
        chain.push(interceptor.fulfilled,interceptor.rejected);
    })
    while(chain.length){
        promise = promise.then(chain.shift(),chain.shift())
    }
}
function interceptorsManner(){
    this.handlers = [];
}
interceptorsManner.prototype.use = function(fulfilled,rejected){
    this.handlers.push({
        fulfilled:fulfilled,
        rejected:rejected
    })
}

2.利用职责链组织一个表单验证
需求:有一个表单,需要先前台校验,在后端校验

//表单事件绑定 -> 表单前端验证 -> 表单后端验证
//好处:随时可以在中间加入新的验证方法
//思想:把你要做的事情拆分成模块,模块之间只做自己模块的事情
InputDeviceInfo.onblur=function(){
    var _value = input.value;
    var _arr = [font,back];
    async function test(){
        var _result = _value;
        while(_arr.length > 0){
            _result = await _arr.shift()(_result);
        }
        return _result;
    }
    test().then((res)=>{
        console.log(res);
    })
}

function font(result){

}
function back(){

}

访问者模式的示例

1.不同角色访问数据
需求:假设有一个公司的财务报表。财务关心支出和收入,老板关心盈利

function report(){
    this.income = ""
    this.const=""
    this.profit=""
}
function boss(){

}
boss.prototype.get = function(data){

}
function account(){

}
account.prototype.get = function(num1,num2){
    
}
function vistor(data,man){
    var handle={
        boss:function(data){
            man.get(data.profit);
        },
        account:function(data){
            man.get(data.income,data.cost);
        }
    }
    handle[man.constructor.name](data);
}
vistor(new report(),new boss());
vistor(new report(),new account());

2.表格操作
需求:一个可以新增,删除的表格

function table(){

}
table.prototype.show = function(){

}
table.prototype.delete = function(){
    vistor(this,tableData,'delete',id)
}
table.prototype.add = function(){
    
}
var tableData = [{
    id:1,
    name:'xxx',
    price:'xxx'
}];

function vistor(table,data,handle){
    var handleOb = {
        delete:function(id){

        },
        add:function(id,name,price){

        }
    }
    var arg = Array.prototype.splice(arguments);
    arguments.splice(0,3);
    handleOb[handle].apply(this,arg);
}

课程小结

1.观察者模式
适用于不适合直接沟通的模块之间的组织
2.职责链模式
组织同步模块,把要做的事情划分为模块,要做的事情一次传递
3.访问者模式
解耦数据操作与数据结构

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,616评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,020评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,078评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,040评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,154评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,265评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,298评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,072评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,491评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,795评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,970评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,654评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,272评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,985评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,815评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,852评论 2 351

推荐阅读更多精彩内容