1 设计原则概述

  1. UNIX/LINUX设计哲学》设计准则

    ① 小既是美。

    ② 每个程序只做一件事情。

    ③ 快速建立原型。

    ④ 舍弃高效率而取可移植性。

    ⑤ 避免强制性的图形化界面交互。

    ⑥ 让每个程序都成为过滤器。

    ⑦ 寻求90%的解决方案。

    注释:花20%的成本解决80%的需求。
  2. 五大设计原则(SOLID)

    S - 单一职责原则

    O - 开放封闭原则

    L - 李氏置换原则

    I - 接口独立原则

    D - 依赖倒置原则
  3. 单一职责原则

    一个程序只做好一件事情。
  4. 开放封闭原则

    对扩展开放,对修改封闭。

    增加需求时,扩展新代码,而非修改已有代码。
  5. 李氏置换原则

    子类能覆盖父类。

    父类能出现的地方子类就能出现。
  6. 接口独立原则

    保持接口的独立,避免出现“胖接口”。
  7. 依赖倒置原则

    面向接口编程,依赖于抽象而不依赖于具体。

2 单一职责原则

  1. 简介

    就一个类、对象以及方法而言,应该仅有一个引起它变化的原因。

    注释:单一职责原则定义为“引起变化的原因”。如果我们有两个动机去改写一个方法,那么这个方法就具有两个职责。
  2. 原则

    一个对象(方法)只做一件事情。
  3. 设计模式验证

    ① 代理模式

    图片预加载代理模式中,代理对象负责预加载职责,本体对象负责图片加载职责。

    ② 迭代器模式

    迭代器模式提供遍历访问聚合对象的职责。

    ③ 单例模式

    将创建对象与管理单例分别封装在两个方法中,两个方法相互独立互不影响。

    ④ 装饰者模式

    让类或者对象一开始只具有一些基础的职责,更多的职责在代码运行时被动态装饰到对象上面。装饰者模式可以为对象动态增加职责,从另一个角度来看, 这也是分离职责的一种方式。
  4. 应用场景

    ① 如果有两个职责总是同时变化,那就不必分离他们。即使两个职责已经被耦合在一起,但它们还没有发生改变的征兆,那么也许没有必要主动分离它们。

    ② 在方便性与稳定性之间要有一些取舍。具体是选择方便性还是稳定性,并没有标准答案,而是要取决于具体的应用环境。例如:jQueryattr 是个非常庞大的方法,既负责赋值,又负责取值,这对于jQuery的维护者来说,会带来一些困难,但对于jQuery的用户来说,却简化了用户的使用。
  5. 优缺点

    ① 优点

    按照职责把对象分解成更小的粒度,降低了单个类或者对象的复杂度,有助于代码的复用,也有利于进行单元测试。

    ② 缺点

    增加了编写代码的复杂度,也增大了这些对象之间相互联系的难度。

3 最少知识原则

  1. 简介

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

    单一职责原则指导我们把对象划分成较小的粒度,提高对象的可复用性。但越来越多的对象之间可能会产生错综复杂的联系,如果修改了其中一个对象,很可能会影响到跟它相互引用的其他对象。

    最少知识原则要求我们尽量减少对象之间的交互。如果两个对象之间不必彼此直接通信,那么这两个对象就不要发生直接的相互联系。
  3. 设计模式验证

    ① 中介者模式

    增加一个中介者对象,让所有的相关对象都通过中介者对象来通信,而不是互相引用。当一个对象发生改变时,只需要通知中介者对象即可。

    ② 外观模式

    外观模式对客户提供一个简单易用的高层接口,高层接口会把客户的请求转发给子系统来完成具体的功能实现。

4 开放-封闭原则

  1. 简介

    软件实体(类、模块、函数)等应该是可以扩展的,但是不可修改。
  2. 原则

    当需要改变一个程序的功能或者给这个程序增加新功能的时候,可以使用增加代码的方式,但是不允许改动程序的源代码。
  3. 实现方式

    通过封装变化的方式,可以把系统中稳定不变的部分和容易变化的部分隔离开来。

    (1) 利用对象多态性

    利用对象的多态性来消除条件分支语句。

    (2) 放置挂钩

    在程序有可能发生变化的地方放置一个挂钩,挂钩的返回结果决定了程序的下一步走向。

    (3) 回调函数

    把一部分易于变化的逻辑封装在回调函数里,然后把回调函数当作参数传入一个稳定和封闭的函数中。
  4. 设计模式验证

    ① 观察者模式

    当有新的订阅者出现时,发布者的代码不需要进行任何修改;同样当发布者需要改变时,也不会影响到之前的订阅者。

    ② 模板方法模式

    子类的方法种类和执行顺序都是不变的,所以我们把这部分逻辑抽出来放到父类的模板方法里面;而子类的方法具体怎么实现则是可变的,于是把这部分变化的逻辑封装到子类中。通过增加新的子类,便能给系统增加新的功能,并不需要改动抽象父类以及其他的子类。

    ③ 策略模式

    策略模式将各种算法都封装成单独的策略类,这些策略类可以被交换使用。策略和使用策略的客户代码可以分别独立进行修改而互不影响。

    ④ 代理模式

    图片预加载示例中,代理函数proxyMyImage负责图片预加载,myImage图片加载函数不需要任何改动。

    ⑤ 职责链模式

    新增处理函数时,不需要改动原有的链条节点代码,只需要在链条中增加一个新的节点。

5 代码重构

  1. 提炼函数

    如果在函数中有一段代码可以被独立出来,那我们最好把这些代码放进另外一个独立的函数中。
var getUserInfo = function () {
ajax('http:// xxx.com/userInfo', function (data) {
console.log('userId: ' + data.userId);
console.log('userName: ' + data.userName);
console.log('nickName: ' + data.nickName);
})
} //改成
var getUserInfo = function () {
ajax('http:// xxx.com/userInfo', function (data) {
printDetails(data);
});
};
var printDetails = function (data) {
console.log('userId: ' + data.userId);
console.log('userName: ' + data.userName);
console.log('nickName: ' + data.nickName);
};
  1. 合并重复的条件片段

    如果一个函数体内有一些条件分支语句,而这些条件分支语句内部散布了一些重复的代码,那么就有必要进行合并去重工作。
var paging = function (currPage) {
if (currPage <= 0) {
currPage = 0;
jump(currPage); // 跳转
} else if (currPage >= totalPage) {
currPage = totalPage;
jump(currPage);
} else {
jump(currPage);
}
}; //改成
var paging = function (currPage) {
if (currPage <= 0) {
currPage = 0;
} else if (currPage >= totalPage) {
currPage = totalPage;
}
jump(currPage); // 把 jump 函数独立出来
};
  1. 把条件分支语句提炼成函数

    在程序设计中,复杂的条件分支语句是导致程序难以阅读和理解的重要原因,而且容易导致一个庞大的函数。
var getPrice = function (price) {
var date = new Date();
if (date.getMonth() >= 6 && date.getMonth() <= 9) {
return price * 0.8;
}
return price;
}; //改成
var isSummer = function () {
var date = new Date();
return date.getMonth() >= 6 && date.getMonth() <= 9;
};
var getPrice = function (price) {
if (isSummer()) { // 夏天
return price * 0.8;
}
return price;
};
  1. 合理使用循环

    在函数体内,如果有些代码实际上负责的是一些重复性的工作,那么合理利用循环不仅可以完成同样的功能,还可以使代码量更少。
var createXHR = function () {
var xhr;
try {
xhr = new ActiveXObject('MSXML2.XMLHttp.6.0');
} catch (e) {
try {
xhr = new ActiveXObject('MSXML2.XMLHttp.3.0');
} catch (e) {
xhr = new ActiveXObject('MSXML2.XMLHttp');
}
}
return xhr;
};
var xhr = createXHR(); //改成
var createXHR = function () {
var versions = ['MSXML2.XMLHttp.6.0ddd', 'MSXML2.XMLHttp.3.0', 'MSXML2.XMLHttp'];
for (var i = 0, version; version = versions[i++];) {
try {
return new ActiveXObject(version);
} catch (e) {
}
}
};
var xhr = createXHR();
  1. 提前让函数退出代替嵌套条件分支

    嵌套的条件分支语句绝对是代码维护者的噩梦。嵌套的条件分支往往是由一些深信“每个函数只能有一个出口的”程序员写出的。但实际上,如果对函数的剩余部分不感兴趣,那就应该立即退出。
var del = function (obj) {
var ret;
if (!obj.isReadOnly) { // 不为只读的才能被删除
if (obj.isFolder) { // 如果是文件夹
ret = deleteFolder(obj);
} else if (obj.isFile) {
ret = deleteFile(obj);
}
}
return ret;
}; var del = function (obj) {
if (obj.isReadOnly) {
return;
}
if (obj.isFolder) {
return deleteFolder(obj);
}
if (obj.isFile) {
return deleteFile(obj);
}
};
  1. 传递对象参数代替过长的参数列表

    有时候一个函数有可能接收多个参数,而参数的数量越多,函数就越难理解和使用。在使用的时候,还要小心翼翼,以免少传了某个参数或者把两个参数搞反了位置。

    这时我们可以把参数都放入一个对象内,不用再关心参数的数量和顺序,只要保证参数对应的 key 值不变就可以了。
  2. 尽量减少参数数量

    在实际开发中,向函数传递参数不可避免,但我们应该尽量减少函数接收的参数数量。
  3. 少用三目运算符

    如果条件分支逻辑简单且清晰,这无碍我们使用三目运算符;但如果条件分支逻辑非常复杂,我们最好的选择还是按部就班地编写 if...else...
  4. 合理使用链式调用

    经常使用jQuery的程序员相当习惯链式调用方法,在JavaScript 中,可以很容易地实现方法的链式调用,即让方法调用结束后返回对象自身。

    使用链式调用的方式可以省下一些字符和中间变量,但调试时不方便。如果我们知道一条链中有错误出现,必须得先把这条链拆开才能加上一些调试log或者增加断点。

    如果该链条的结构相对稳定,后期不易发生修改,可以使用链式调用。如果该链条很容易发生变化,导致调试和维护困难,那么还是建议使用普通调用的形式。
  5. 分解大型类

    面向对象设计鼓励将行为分布在合理数量的更小对象之中。
  6. return退出多重循环

    假设在函数体内有一个两重循环语句,我们需要在内层循环中判断,当达到某个临界条件时退出外层的循环。我们大多数时候会引入一个控制标记变量或设置循环标记。

    这两种做法无疑都让人头晕目眩,更简单的做法是在需要中止循环的时候直接退出整个方法。

    如果在循环之后还有一些将被执行的代码,我们可以把循环后面的代码放到 return 后面,如果代码比较多,就应该把它们提炼成一个单独的函数。

JavaScript设计原则与编程技巧的更多相关文章

  1. 【设计原则和编程技巧】单一职责原则 (Single Responsibility Principle, SRP)

    单一职责原则 (Single Responsibility Principle, SRP) 单一职责原则在设计模式中常被定义为“一个类应该只有一个发生变化的原因”,若我们有两个动机去改写一个方法,那这 ...

  2. Javascript设计原则

    Javascript设计原则 在面向对象的程序设计思想中, 我们能够遵循一些原则能够让我们开发代码时结构层次清晰, 更具说服力, 可谓是事半功倍. 做到这一点我们掌握一些程序设计原则是非常有利的, 如 ...

  3. javascript的api设计原则

    前言 本篇博文来自一次公司内部的前端分享,从多个方面讨论了在设计接口时遵循的原则,总共包含了七个大块.系卤煮自己总结的一些经验和教训.本篇博文同时也参考了其他一些文章,相关地址会在后面贴出来.很难做到 ...

  4. 15个提高编程技巧的JavaScript工具

    原文地址:http://www.imooc.com/wenda/detail/243523 JavaScript脚本库是一个预先用JavaScript语言写好的库,它方便了我们开发基于JavaScri ...

  5. 《设计模式之美》 <03>面向对象、设计原则、设计模式、编程规范、重构,这五者有何关系?

    面向对象 现在,主流的编程范式或者是编程风格有三种,它们分别是面向过程.面向对象和函数式编程.面向对象这种编程风格又是这其中最主流的.现在比较流行的编程语言大部分都是面向对象编程语言.大部分项目也都是 ...

  6. JavaScript 的 API设计原则

    一.接口的流畅性 好的接口是流畅易懂的,他主要体现如下几个方面: 1.简单 操作某个元素的css属性,下面是原生的方法: document.querySelectorAll('#id').style. ...

  7. 连载:面向对象的葵花宝典:思考、技巧与实践(39) - 设计原则 vs 设计模式

    它的设计原则,和设计模式,是否该用它? ============================================================================= 在& ...

  8. JavaScript设计模式之设计原则

    何为设计 即按照哪一种思路或者标准来实现功能,功能相同,可以有不同的设计方案来实现 伴随着需求的增加,设计的作用就会体现出来,一般的APP每天都在变化,更新很快,需求不断在增加,如果设计的不好,后面很 ...

  9. SOA 实现:服务设计原则

    http://www.ibm.com/developerworks/cn/webservices/ws-soa-design/ 引言 面向服务的体系结构(Service-Oriented Archit ...

随机推荐

  1. 【LeetCode】590. N-ary Tree Postorder Traversal 解题报告 (C++&Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 递归 迭代 相似题目 参考资料 日期 题目地址:htt ...

  2. 图片 Augmentation整理

    目录 Augmentation Flipping 翻转 Grayscale Equalize 均衡直方图 Posterize 减少颜色通道位数 Cropping Rotation Translatio ...

  3. 编写Java程序,实现客户端向服务端上传文件的功能

    查看本章节 查看作业目录 需求说明: 实现客户端向服务端上传文件的功能 当启动服务端后,运行客户端程序,系统提示客户在客户端输入上传文件的完整路径.当客户在客户端输入完成后,服务端实现文件上传 实现思 ...

  4. .net core的配置介绍(二):自定义配置(Zookeeper,数据库,Redis)

    上一篇介绍了.net core的配置原理已经系统提供的一些常用的配置,但有时我们的配置是存放在Zookeeper,DB,Redis中的,这就需要我们自己去实现集成了. 这里再介绍几个我们用的多的配置集 ...

  5. winform 自定义自动完成控件

    做过前端的朋友肯定很清楚自动完成控件,很多优秀的前端框架都会带有自动完成控件,同样的,winform也有,在我们的TextBox和ComboBox中,只需要设置AutoCompleteSource属性 ...

  6. 使用 Docker 构建和运行自己的镜像

    步骤 首先,从 GitHub 中克隆示例项目: git clone https://github.com/dockersamples/node-bulletin-board cd node-bulle ...

  7. vue再页面渲染json数据时没有显示

    对象点属性不能获取数据. 原因: 在创建数据对象时我使用了k,v方式:tempMap['category '] = this.category[i].label 如果在创建数据时使用的k,v方式,那么 ...

  8. 禁止yum update 自动更新系统内核

    使用yum update更新系统软件时,禁止升级内核,可以防止产生因不兼容导致的未知错误. 设置前请先备份原设置文件yum.conf cp /etc/yum.conf    /etc/yum.conf ...

  9. linux安全篇:禁止频繁访问的ip访问nginx

    实验环境 版本:redhat6.5ip:172.16.1.100,172.16.10软件:nginx 172.16.1.10部署nginx [root@localhost tools]# lsngin ...

  10. Centos7安装maxscale 实现mysql的读写分离

    安装依赖 yum install -y novacom-server.x86_64 libaio.x86_64 libaio-devel.x86_64 网站下载 https://downloads.m ...