面向对象设计模式的核心法则


Posted in Javascript onNovember 10, 2013

1. 单一职责

就一个类而言,应该仅有一个引起它变化的原因。
如果一个类承担的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会削弱或者抑制这个类完成其他职责的能力。这种耦合会导致脆弱的设计,当变化发生时,设计会遭到意想不到的破坏。
软件设计真正要做的许多内容,就是发现职责并把那些职责互相分离。如果你多于一个动机去改变一个类,那么这个类就具有多于一个的职责。

2. 开放封闭

软件实体(类,模块,函数等)应该可以扩展,但是不可修改。也就是说,对于扩展是开放的,对于更改是封闭的。
如此设计,面对需求的改变可以保持相对的稳定,从而使系统可以在第一个版本以后不断的推出新的版本。
无论模块是多么的'封闭',都会存在一些无法对之封闭的变化。既然不可能完全封闭,设计人员必须对于他设计的模块应该对哪种变化封闭做出选择。他必须先猜测出最有可能发生的变化种类,然后构造抽象来隔离那些变化。
等到变化发生时立即采取行动。

在我们最初编写代码时,假设变化不会发生。当变化发生时,我们就创建抽象来隔离以后发生的同类变化。
面对需求,对程序的改动是通过增加新代码进行的,而不是更改现有的代码。
我们希望的是在开发工作展开不久就知道可能发生的变化。查明可能发生的变化所等待的时间越长,要创建正确的抽象就越困难。
开放-封闭原则是面向对象设计的核心所在。遵循这个原则可以带来面向对象技术所声称的巨大好处,也就是可维护、可扩展、可复用、灵活性好。开发人员应该仅对程序中呈现出频繁变化的那些部分做出抽象,然而,对于应用程序中的每个部分都可以的进行抽象同样不是一个好主意。拒绝不成熟的抽象和抽象本身一样重要。

3. 依赖倒转

高层模块不应该依赖底层模块。两个都应该依赖抽象。
抽象不应该依赖细节,细节应该依赖抽象。
抽象不应该依赖细节,细节应该依赖于抽象,针对接口编程,不要对实现编程。
依赖倒转其实可以说是面向对象设计的标志,用哪种语言来写程序并不重要,如果编写时考虑的都是如何针对抽象编程而不是针对细节编程, 即程序中所有的依赖关系都终止于抽象类或者接口,那就是面向对象的设计,反之那就是过程化的设计了。

4. 里氏代换

一个软件实体如果使用的是一个父类的话,那么一定适用于其子类,而且察觉不出父类对象与子类对象的区别。也就是说,在软件里面,把父类都替换成它的子类,程序的行为没有变化。
子类型必须能用替换掉它们的父类型。
只有当子类可以替换掉父类,软件单位的功能不受到影响时,父类才能真正被复用,而子类也能够在父类的基础上增加新的行为。

5. 合成/聚合复用

尽量使用合成/聚合,尽量不要使用类继承。
优先使用对象的合成/聚合将有助于你保持每个类被封装并被集中在单个任务上,这样累和类继承层次会保持较小的规模,并且不大可能增长为不可控制的庞然大物。

6. 迪米特法则

如果两个类不必彼此直接通信,那么着两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。
在类的结构设计上,每一个类都应当尽量降低成员的访问权限,也就是说,一个类包装好自己的private状态,不需要让别的类知道的字段或行为就不要公开。
迪米特法则其根本思想是强调了类之间的松耦合。

类之间的耦合越弱,越有利于复用,一个处在弱耦合的类被修改,不会对有关系的类造成波及。

辅助资料:

常用创建型设计模式(其他类型模式就不提了,自己看书)

创建型模式隐藏了这些类的实例是如何被创建和放在一起,整个系统关于这些对象所知道的是由抽象类所定义的接口。这样,创建型模式在创建了什么、谁创建它=它是怎么被创建的,以及何时创建这些方面提供了很大的灵活性。

1. 工厂方法模式(Factory Method)

定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂模式使一个类的实例化延迟到其子类。
创建型模式抽象了实例化的过程,它们帮助一个系统独立于如何创建、组合和表示它的那些对象。创建型模式都会将关于该系统使用哪些具体的类的信息封装起来。允许客户用结构和功能差别个很大的'产品'对象配置一个系统。配置可以是静态的,即在编译时制定,也可以是动态的,就是运行时再指定。
通常设计应该是从工厂方法开始,当设计者发现需要更大的灵活性时,设计便会向其他创建型模式演化。当设计者在设计标准之间进行权衡的时候,了解多个创建型模式可以给设计者更多的选择余地。

2. 抽象工厂模式(Abstract Factory)

提供一个创建一系列或者相关依赖对象的接口,而无需指定它们具体的类。

3. 建造者模式(Builder)

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
内聚性与耦合性 内聚性描述的是一个例程内部组成部分之间相互联系的紧密程度。而耦合性描述的是一个例程与其他例程之间联系的紧密程度。软件开发的目标应该是创建这样的例程:内部完整,也就是高内聚,而与其他例程之间的联系则是小巧、直接、可见、灵活的,这样就是松耦合。
将一个复杂对象的构建与它的表示分离,这就可以很容易地改变一个产品的内部表示,并且使得构造代码和表示代码分开。这样对于客户来说,它无需关心产品的创建过程,而只要告诉我需要什么,我就能用同样的构建过程创建不同的产品给客户。

4. 原型模式(Prototype)

用原型的实例制定创建对象的种类,并且通过拷贝这些原型创建新的对象。
建立相依数目的原型并克隆它们通常比每次用合适的状态手工实例化该类更方便一些。

5. 单例模式(Singleton)

保证一个类仅有一个实例,并提供一个访问它的全局访问点。
对一些类来说,一个实例是很重要的。一个全局变量可以使得一个对象被访问,但它不能防止客户实例化多个对象。单例的优势就是让类自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建,并且单例还提供了一个访问该实例的方法。这样就使得对唯一的实例可以严格地控制客户怎样以及何时访问它。

Javascript 相关文章推荐
在JavaScript中实现命名空间
Nov 23 Javascript
用 Javascript 验证表单(form)中的单选(radio)值
Sep 08 Javascript
Extjs grid panel自带滚动条失效的解决方法
Sep 11 Javascript
基于jquery实现动态竖向柱状条特效
Feb 12 Javascript
分分钟玩转Vue.js组件
Oct 25 Javascript
vue.js学习笔记:如何加载本地json文件
Jan 17 Javascript
js学习总结之DOM2兼容处理重复问题的解决方法
Jul 27 Javascript
webpack学习教程之前端性能优化总结
Dec 05 Javascript
深入理解JS的事件绑定、事件流模型
May 13 Javascript
Vue 通过公共字段,拼接两个对象数组的实例
Nov 07 Javascript
JS数据类型(基本数据类型、引用数据类型)及堆和栈的区别分析
Mar 04 Javascript
vue组件中传值EventBus的使用及注意事项说明
Nov 16 Javascript
JavaScript 语言基础知识点总结(思维导图)
Nov 10 #Javascript
JS增加行复制行删除行的实现代码
Nov 09 #Javascript
javascript相等运算符与等同运算符详细介绍
Nov 09 #Javascript
js实现简单登录功能的实例代码
Nov 09 #Javascript
ExtJS实现文件下载的方法实例
Nov 09 #Javascript
简单的两种Extjs formpanel加载数据的方式
Nov 09 #Javascript
5分钟理解JavaScript中this用法分享
Nov 09 #Javascript
You might like
用php获取远程图片并把它保存到本地的代码
2008/04/07 PHP
检查用户名是否已在mysql中存在的php写法
2014/01/20 PHP
PHP5全版本绕过open_basedir读文件脚本漏洞详细介绍
2015/01/20 PHP
php制作动态随机验证码
2015/02/12 PHP
Symfony2联合查询实现方法
2016/03/18 PHP
PHP入门教程之使用Mysqli操作数据库的方法(连接,查询,事务回滚等)
2016/09/11 PHP
PHP实现双链表删除与插入节点的方法示例
2017/11/11 PHP
PHP重载基础知识回顾
2020/09/10 PHP
JavaScript 获得选中文本内容的方法
2009/02/15 Javascript
javascript 动态设置已知select的option的value值的代码
2009/12/16 Javascript
Javascript下判断是否为闰年的Datetime包
2010/10/26 Javascript
JavaScript高级程序设计 阅读笔记(二十一) JavaScript中的XML
2012/09/14 Javascript
JSON序列化与解析原生JS方法且IE6和chrome测试通过
2013/09/05 Javascript
jquery checkbox实现单选小例
2013/11/27 Javascript
深入理解JavaScript系列(48):对象创建模式(下篇)
2015/03/04 Javascript
jQuery使用drag效果实现自由拖拽div
2015/06/11 Javascript
原生JS实现仿淘宝网左侧商品分类菜单效果代码
2015/09/10 Javascript
Angular2入门教程之模块和组件详解
2017/05/28 Javascript
Vue学习笔记进阶篇之vue-router安装及使用方法
2017/07/19 Javascript
Javascript 之封装(Package)
2018/09/14 Javascript
微信小程序实现点击卡片 翻转效果
2019/09/04 Javascript
python使用BeautifulSoup分析网页信息的方法
2015/04/04 Python
python3操作微信itchat实现发送图片
2018/02/24 Python
Python button选取本地图片并显示的实例
2019/06/13 Python
浅谈OpenCV中的新函数connectedComponentsWithStats用法
2020/07/05 Python
Django+Django-Celery+Celery的整合实战
2021/01/20 Python
详解canvas drawImage()方法绘制图片不显示的问题
2018/10/08 HTML / CSS
移动端html5判断是否滚动到底部并且下拉加载
2019/11/19 HTML / CSS
自荐书范文
2013/12/08 职场文书
集团公司党的群众路线教育实践活动工作总结
2014/03/03 职场文书
小学教师培训方案
2014/06/09 职场文书
2015领导干部廉洁自律工作总结
2015/07/23 职场文书
体育教师教学随笔
2015/08/15 职场文书
2016继续教育研修日志
2015/11/13 职场文书
浅析MySQL如何实现事务隔离
2021/06/26 MySQL
使用GO语言实现Mysql数据库CURD的简单示例
2021/08/07 Golang