提高可扩展性(上)

提供可扩展性的目的

  1. 面对需求变更,方便需求更改
  2. 减少代码修改的难度

什么是好的可扩展

  1. 需求的变更,不需要重写
  2. 代码修改不会引起大规模变动
  3. 方便加入新模块

低耦合

提供可扩展性的设计模式

更好的更改代码

1.适配器模式
目的:通过写一个适配器,来代替替换
应用场景:面临接口不通用的问题
2.装饰着模式
目的:不重写方法的扩展方法
应用场景:当一个方法需要扩展,但是又不好去修改方法

解耦你的方法和调用

1.命令模式
目的:解耦实现和调用,让双方互不干扰
应用场景:调用的命令充满不确定性

基本结构

适配器模式的基本结构

现在公司想用log来代替console.log

var log = (function(){
    return window.console.log
})()

装饰者模式的基本结构

我们新建一个自己的方法,在其内部调用b方法,并且再执行自己的方法。这样可以再不修改原对象的情况下,扩展行为

//有一个他人写好的模块a,内部的方法b,模块为他人写好,不能修改,如何扩展b方法?
var a = {
    b:function(){

    }
}
function myb(){
    a.b();
    //要扩展的b方法
}

命令模式的基本结构

var command=(function(){
    var action = {

    };
    return function excute(){}
})();

应用示例

适配器模式的示例

  1. 框架的变更
    需求:目前项目使用的A框架,现在改成了B,两个框架十分类似,但是有少几个方法不同
//A.c() => $.css()
//A.o() => $.on()

window.A = $
A.c = functions(){
    return $.css.apply(this,arguments);
}
A.o = functions(){
    return $.on.apply(this,arguments);
}
  1. 参数适配
    需求:为了避免参数不适配产生问题,很多框架会有一个参数适配操作
//当你的方法传入的参数较为复杂,最好都加上这么一个参数适配
function f1(config){
    var _default={
        name:'xxx',
        color:'red',
    }
    for(var item in _default){
        _default[item] = config[item] || _default[item]
    }
}

装饰者模式的示例

  1. 扩展你的已有事件绑定
    需求:现在项目改造,需要给input标签已经有的事件,增加一些操作
var decorater = function(dom,fn){
    if(typeof dom.onclick=="function"){
        var _old = dom.onclick;
        dom.onclick=function(){
            _old();
            fn();
        }
    }
}
decorater(document.getElementById('dom1'),function(){
    console.log(2);
})
  1. Vue的数组监听
    需求:vue中利用defineProperty可以监听对象,那么数组怎么办?
//push,shift 阅读vue源码
var arrayproto = Array.prototype;
var arrayMethods = Object.create(arrayProto);
var methodsToPath = [
    'push',
    'pop',
    'shift',
    'unshift',
    'splice',
    'sort',
    'reverse'
];
methodsToPath.forEach((method) => {
    var original = arrayproto[method];
    var result = original.apply(this,arguments);
    dep.notify();
    return result;
})

命令模式的示例

绘图命令

需求:封装一系列的canvas绘图命令

var canvasCommand = (function(){
    var action = {
        drawCircle:function(){},
        drawRect:function(){},
    }
    return function excute(commander){
        commander.forEach((item) => {
            action[item.command](item.config);
        })
    }
})();

canvasCommand([
    {command:'drawCircle',config:{}},
    {command:'drawRect',config:{}},
    {command:'drawCircle',config:{}},
    {command:'drawCircle',config:{}},
])

绘制随机数量图片

需求:要做一个画廊,图片数量和排列顺序随机

//创建图片HTML -》展示
var createImg = (function(){
    var action = {
        create:function(){
            var htmlArr = [];
            var _htmlstring = '';
            var _htmlTemplate="<div><img src='{{img-url}}' /></div><h2>{{title}}</h2>"
            var displayWay = {
                normal:function(arr){
                    return arr;
                },
                reverse:function(arr){
                    return arr.reverse();
                },
            }
            obj.imgArr.forEach((img) => {
                var _html;
                _html = _htmlTemplate.replace('{{img-url}}',img.img).replace('{{img-url}}',img.title);
                htmlArr.push(_html);
            })
            htmlArr=displayWay[obj.type](htmlArr);
            _htmlstring=htmlArr.join("");
            return "<div>"+_htmlstring+"</div>"
        },
        display:function(obj){
            var _html = this.create(obj);
            obj.target.innerHTML = _html;
        },
    }
    return function excute(obj){
        var _default = {
            imgArr:[{img:"xxxx",title:'default title'}],
            type:'normal',
            target:document.body
        }
        for(var item in _default){
            _default[item] = obj[item] || _default[item]
        }
        action.display(_default);
    }
})();

//1.用户只管输入他要的命令,不用关心api
//2.命令与实现解耦,无论发生变动,不会彼此影响
//数据直接调用api => 数据 -> excute命令解析层 -> 调用api

课程小结

适配器模式:当面临两个新老模块间接口api不匹配,可以用适配来转化api
装饰者模式:当老的方法,不方便去直接修改,可以通过装饰者来增加功能
命令模式:解耦实现和具体命令,让实现端和命令端扩展的都更轻松

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容