• 模式设计原则


    单一职责原则

    单一职责原则(SRP)的职责被定义为“引起变化的原因”。如果我们有两个动机去改写一个方法,那么这个方法就具有两个职责。每个职责都是变化的一个轴线,如果一个方法承担了过多的职责,那么在需求的变迁过程中,需要改写这个方法的可能性就越大。因此,SRP原则体现为:一个对象(方法)只做一件事情

    很多设计模式都遵循了SRP,比如装饰者模式

    Function.prototype.after = function(afterfn) {
      var __self = this;
      return function() {
        var ret = __self.apply(this, arguments);
        afterfn.apply(this, arguments);
        return ret;
      }
    };
    // 职责一
    var showLogin = function() {
      console.log('打开登录浮层');
    };
    // 职责二
    var log = function() {
      console.log('上报标签为: ' + this.getAttribute('tag'));
    };
    
    // 打开登录浮层之后上报数据
    document.getElementById('button').onclick = showLogin.after(log);
    

    SRP 原则的优点是降低了单个类或者对象的复杂度,按照职责把对象分解成更小的粒度,这有助于代码的复用,也有利于进行单元测试。当一个职责需要变更的时候,不会影响到其他的职责。

    SRP 原则也有一些缺点,最明显的是会增加编写代码的复杂度。当我们按照职责把对象分解成更小的粒度之后,实际上也增大了这些对象之间相互联系的难度

    在实际开发中,是否选择让代码符合单一职责原则,要根据具体的环境来定。

    最少知识原则

    最少知识原则(LKP)说的是一个软件实体应当尽可能少地与其他实体发生相互作用。这里的软件实体是一个广义的概念,不仅包括对象,还包括系统、类、模块、函数、变量等

    单一职责原则指导我们把对象划分成较小的粒度,这可以提高对象的可复用性。但越来越多的对象之间可能会产生错综复杂的联系,如果修改了其中一个对象,很可能会影响到跟它相互引用的其他对象。对象和对象耦合在一起,有可能会降低它们的可复用性。在程序中,对象的“朋友”太多并不是一件好事,“城门失火,殃及池鱼”和“一人犯法,株连九族”的故事时有发生

    中介者模式是最少知识原则的很好实践,通过引入一个第三者对象,管理其他子对象,这样就减少了子对象之间的联系,维护时只需要维护第三者对象

    关于中介者模式移步于此

    在实际开发中,是否选择让代码符合最少知识原则,要根据具体的环境来定。

    开放-封闭原则

    在面向对象的程序设计中,开放封闭原则(OCP)是最重要的一条原则。很多时候,一个程序具有良好的设计,往往说明它是符合开放-封闭原则的。

    开放-封闭原则: 软件实体(类、模块、函数)等应该是可以扩展的,但是不可修改

    假设我们是一个大型 Web项目的维护人员,在接手这个项目时,发现它已经拥有 10万行以上的 JavaScript代码和数百个 JS文件。不久后接到一个新需求,即在 window.onload 函数中打印出页面中的所有节点数量,最简单的做法就是打开文本编辑器,搜索出 window.onload 函数在文件中的位置,在函数内部添加以下代码:

    window.onload = function(){
    // 原有代码略
    console.log( document.getElementsByTagName( '*' ).length );
    };
    

    在项目需求变迁的过程中,想要扩展一个模块,最常用的方式当然是修改它的源代码。如果一个模块不允许修改,那么它的行为常常是固定的。然而,改动代码是一种危险的行为,很可能需求解决了,却引来了无数新的bug。按照开放-封闭原则的思想,我们希望在不改动原有代码的情况下,实现新的需求,下面使用装饰者模式打印节点数量

    Function.prototype.after = function(afterfn) {
      var __self = this;
      return function() {
        var ret = __self.apply(this, arguments);
        afterfn.apply(this, arguments);
        return ret;
      }
    };
    window.onload = (window.onload || function() {}).after(function() {
      console.log(document.getElementsByTagName('*').length);
    });
    

    通过动态装饰函数的方式,可以不用理会从前window.onload函数内部实现,无论它的实现优雅或是丑陋,新增的代码和原有的代码可以井水不犯河水

    让程序一开始就尽量遵守开放-封闭原则,并不是一件很容易的事情。一方面,需要知道程序在哪些地方会发生变化,这要求我们有一些“未卜先知”的能力。另一方面,留给我们的开发时间时有限的。因此,在最初编写代码的时候,先假设变化永远不会发生,这有利于我们迅速完成需求。当变化发生并且对我们接下来的工作造成影响的时候,可以再回过头来封装这些变化的地方。确保我们不会掉进同一个坑里,这有点像星矢说的:“圣斗士不会被同样的招数击倒第二次。”

    常用网站: SegmentFault | GitHub | 掘金社区
  • 相关阅读:
    Redis详解(一)——RDB
    十、行锁
    go 上下文context
    go log
    go 结构体取代类
    go select
    go channel
    go 协程(Goroutine)
    go 学习之fmt包
    go 学习之bufio
  • 原文地址:https://www.cnblogs.com/yesyes/p/15375982.html
Copyright © 2020-2023  润新知