资讯专栏INFORMATION COLUMN

单一职责原则之模式的黄金法则

GeekQiaQia / 2905人阅读

摘要:今天说一下,单一职责原则。比如,接口的地址本来已经很完美了,但是你的是处女座最讨厌处女座非要给路由添加几个以保证后台数据的安全。为了过年,我会选择使用,因为不知道处女座以后会做出什么傻事来。此时的使用动态织入后,可以完美的解决处女座。

在设计模式中,有着几条视为黄金原则,设计模式都是围绕黄金原则,对代码或者说是架构设计做出一些相应的调整,久而久之,GoF 4人组,发现其实有些设计思想可以称为模式,能实现代码复用的好处,从而设计模式出世。其实,这些模式的基石就是黄金原则,所以,接下来会对这些原则进行详细的解析。今天说一下,单一职责原则。

谈谈单一职责原则

单一职责原则,英文名叫做SRP.即,Single responsibility principle (装个逼). 我们从字面上,差不多已经完全可以理解这个原则所要表达的意思。在js中,函数永远是一等公民,而函数所代表的就是一份职责。 一个函数完成一个功能,最后编织成了我们的js程序。

前面差不多把模式基本的梳理了一遍,要知道,每个模式里面或多或少会包含一些原则。。。(我编不下去)

说人话呀~~~ 俺们看不懂!!!
客官对不起,小的这就给你上栗子。

单一职责与代理

直接来干货。在代理模式中,大家还记得这个例子吗?图片的加载

在未引入代理模式的时候是这样写的

var delayload = (function(){
    var img = document.querySelector("#img");
    img.src = "loading.gif";
    var newImg = document.createElement("img");
    newImg.onload = function(){
        img.src = newImg.src;
    }
    return function(src){
        newImg.src = src;
    }
})();
delayload("jimmy.jpg");

我们分析一下,在delayload里面存在了两个原则,一个是给本体的img设置src,还有一个是,虚拟构建一个Img节点来加载图片,最后在加载完成的时候,修改本体的src. 这样写,没错,如果在没有其他的需求之前,这个代码可以算是比较完美的。 但是,你的产经永远不会这么一心一意,有时候,会让你把,等待加载的图片换掉,有时候。。。

所以为了扩展性考虑,我们可以参考单一职责原则,修改如下:

//将背景图设置,和图片加载的src修改分开
var delayload = (function(){
    var img = document.querySelector("#img");
    return {
        setSrc:function(src){
            img.src = src;
        }
    }
})();
var proxy = (function(){
    var img = document.createElement("img");
    img.onload = function(){
        delayload.setSrc(img.src);
    }
    return {
        setSrc:function(src){
            delayload.setSrc("loading.gif");
            img.src = src;
        }
    }
})();
proxy.setSrc("jimmy.jpg");

这样一方面,对于本体img设置src的功能我们可以完美的保留下来。

单一职责与节点渲染

相信大家都遇到这个问题,向后台请求数据,然后渲染到页面上。说具体一点就是,像这样的

一本图书的信息,有他的img,title,author这3部分内容。 我们的职责就是,向后台请求相关的数据,然后将数据渲染到页面。而我们目前的职责就是两个,获取数据,然后渲染数据。

var data = {
    img:"http://7xpsmd.com1.z0.glb.clouddn.com/16-1-24/19756676.jpg",
    title:"JS权威指南",
    author:"David Flaagan"
}

http.getBooks = function(url,callback){
    $.ajax(url)
    .then((data)=>{
        itera(data,callback);
    })
}
//要知道,这里的data可能不只一个,我们需要进行遍历
var itera = function(data,callback){
    for(var i = 0,book;book = data[i++];){
        callback(data); //渲染data
    }
}
//请求数据,并且渲染数据
http.getBooks("www.example.com",function(){
    console.log("渲染数据");
});

简单流程是这样的,从大的方面来看,职责确实只有两个,但是我们实现的时候,会发现,本体中嵌套一个for循环,会把添加节点函数带入,这样耦合性会增大,所以这里加了一个迭代器模式,让迭代器来表示循环,即,我的渲染函数只和迭代器发生关系,而你原来的ajax请求是怎么实现的我并不清楚。

可以看出,职责的划分不是一眼就能看出来的,那怎么看嘞?

其实,我也不知道,看感觉呗,有时候感觉来了,挡都挡不住.

获取单例

上面已经说过了,SRP是在模式应用中,最简单的一个,同样也是应用最广的一个。回想一下,我们在写单例的时候,通常的格式是一个闭包+一个变量就over了。

var Weather = function() {}
var getSingle = (function() {
    var single;
    return function(obj) {
        if (single === undefined) {
            return single = obj;
        }
        return single;
    }
})();
var weather1 = getSingle(new Weather());  //原始的Weather
var weather2 = getSingle(new Weather());  //存储的single

这里,将单例类和获取单例的工厂分开来。 工厂可以无限制使用,单例类也可以执行他独特的行为。 这样做是极好的。 当然,我们也可以创造不同的工厂出来。

这个是缓存一个功能函数的结果,应用场景主要在加载额外的模板文件时,使用

var getSingle = function(fn){
    var result;
    return function(){
        return result || (result = fn.apply(this,arguments));
    }
}
AOP之SRP

AOP我们应该算是阅人无数的级别了, 在很多地方都是用过他,职责链模式,装饰者模式等。而AOP也是完美体现SRP原则的。

首先,他本身的书写都是符合SRP原则

Function.prototype.before = function(fn){
    var _this = this;
    return function(){
        fn.apply(this,arguments);  //值为Boolean,表示是否继续向下传递
        return    _this.apply(this,arguments);
    }
}

将AOP的概念抽象化,然后就可以直接使用beofre。

通常我们可以将AOP运用到,修改url参数,传递权限的业务上面。 比如,接口的地址本来已经很完美了,但是你的leader是处女座(最讨厌处女座),非要给url路由添加几个token以保证后台数据的安全。现在有两条路给你,要么直接改动路由,要么可以使用AOP进行改动。 为了过年,我会选择使用AOP,因为不知道处女座以后会做出什么傻事来。

function dealUrl(url){
    url+=param.getToken();
}
http.ajax = http.ajax.before(dealUrl);
http.ajax("www.example.com");   //此时的Url = www.example.com?token=23jkfd3kjfdksjfkjds

使用before动态织入后,可以完美的解决处女座。

如何做到SRP原则

实话说,我真的不知道。 我这里只有几条我认为比较好的经验给大家,因为如果过分追求设计的话,你的程序复杂度将会爆炸!!!。 在合适的时间,合适的位置使用,这才是SRP的难点。

说一下,不是用SRP原则的时候把。

分清行为和动作。 我们只是用SRP区分动作,而不过分划分行为。行为就是: 创建div,添加类,修改attr等基本操作。 动作就是 将行为组合在一起达到的效果,比如发送请求,渲染节点。 这类比较抽象的动作。

要以第一感觉为主,如果感觉这样划分职责没错,使用SRP恰到好处,那就干吧。 反正以后自已挖的坑自己也得补回来,要知道,没有重构过的代码,永远是不能看的(说的是我。。。)。

其实有时候,从正面走不行,我们可以尝试一下逆向思维,想想,你平常没有使用SRP原则是什么时候就可以了。这样能够帮助你思维的发展,也能让你写出一手好代码。

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

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

相关文章

  • Java设计模式七大原则

    摘要:单一职责原则开闭原则里氏替换原则依赖倒置原则接口隔离原则迪米特法则组合聚合复用原则单一职责原则高内聚低耦合定义不要存在多于一个导致类变更的原因。建议接口一定要做到单一职责,类的设计尽量做到只有一个原因引起变化。使用继承时遵循里氏替换原则。 单一职责原则 开闭原则 里氏替换原则 依赖倒置原则 接口隔离原则 迪米特法则 组合/聚合复用原则 单一职责原则(Single Responsi...

    Olivia 评论0 收藏0
  • Java设计模式-六大原则

    摘要:依赖倒置原则是个设计原则中最难以实现的原则,它是实现开闭原则的重要途径,依赖倒置原则没有实现,就别想实现对扩展开放,对修改关闭。 1、单一职能原则(Single Responsibility Principle, SRP) 定义 There should never be more than one reason for a class to change.应该有且仅有一个原因引起类的...

    molyzzx 评论0 收藏0
  • 设计模式六大原则(PHP)

    摘要:常用的六大设计模式有单一职责原则,里氏替换原则,依赖倒转原则,接口隔离原则,迪米特法则,开闭原则。这六大原则是最虚,最抽象的,很难理解。这就是接口隔离原则。当我们遵循前面介绍的五大原则,以及使用种设计模式的目的就是遵循开闭原则。   设计模式的目的是为了更好的代码重用性,可读性,可靠性和可维护性。常用的六大设计模式有:单一职责原则(SRP),里氏替换原则(LSP),依赖倒转原则(DIP...

    bluesky 评论0 收藏0
  • 设计模式系列(总纲)

    摘要:前言关于设计模式,想必大家的第一感觉就是过于高深,有点虚吧。为什么要学习设计模式因为要装逼啊咳咳,大家请忽略前面那句话。处处都是设计模式的体现,所以若想攻下,设计模式是必学的。下节预告单例模式 前言 关于设计模式,想必大家的第一感觉就是过于高深,有点虚吧。相对来说,我们还是更熟悉ssh或者ssm之类的开发框架,一个工具用久了就会熟能生巧,就像刷漆工,时间长了也知道如何刷的一手漂亮的好墙...

    leiyi 评论0 收藏0
  • 开放封闭原则模式黄金法则

    摘要:开放封闭原则应该算是这几个原则里面最容易理解的一个。另外,语句就是开放封闭原则的死敌这个是状态模式中的一个例子。处理开放封闭模式的特例我们都是人,不可能一开始都写出完美的代码。 开放-封闭原则应该算是这几个原则里面最容易理解的一个。它的宗旨就是:如果你想扩展或者改变一个程序的功能,可以增加代码,但是不能改变程序的源码。如果,是对于那些码农来说,最快捷的办法就是改变源码,但是我们面向的是...

    MasonEast 评论0 收藏0

发表评论

0条评论

GeekQiaQia

|高级讲师

TA的文章

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