面向对象六大基本原则
1.开闭原则
很多教程都把开闭原则作为这六大原则中最基本的原则,也就是说他是各个原则的核心。开闭原则指的是,一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。
对于开闭原则,我们在设计软件的时候,首先要搞清楚程序当中什么是未来可能变化的,什么是未来不会变化的。对于可能变化的东西,我们要提前给与可以对应的扩展接口。当然实际开发中,即便是我们认为这些不会变化的地方,未来还是可能变化的,这种变化就只能改代码了,但是这种修改仅仅只是改变个别细节,整体架构往往不会变化。而对于可能变化的地方,我们要给出可以足够扩展的空间,让其能够自由扩展,基本发生了重大的需求变更,整体架构也不会受影响。
例如:工厂模式中,我们将创建对象的过程封装了起来,这样创建对象对的过程中,创建的代码就和调用的代码尽可能地解除了耦合。创建过程可能是变化的,而调用过程往往是不变的。我们创建一个对象之后,需要为其初始化,设定一些配置,这个过程需要我们给出可以扩展的余地,而且要求扩展的时候不能影响调用部分,所以需要使用工厂模式,将可变的创建过程封装起来,供不变的调用模块。
这样说来,开闭原则的核心是解耦了?没错,我认为开闭原则讲的就是解耦,但是他要求我们在设计的时候,重点要预判出什么地方是会发生变化的,并要为变化的地方留出余地。他强调的是对于可变部分进行解耦,使用扩展的方式而不是修改的方式应对变化,这样可以保证程序整体不会发生大的变化。
开闭原则对于开发框架、可以被复用的组件(如jar、dll、js插件等待)尤为重要,因为这些组件必须留出足够的空间去让调用者去扩展自己的业务。所以我们在开发这种组件的时候api才是最难设计的,因为我们设计的API必须能满足调用者对他的全部扩展,这样才能实现调用者在不修改组件代码的情况下实现自己的需求。
2.里氏替换原则
这个原则挺简单,讲的就使用接口的时候,我们必须确保子类能够替换父类所出现的任何地方。纯粹就字面的意思来讲,就是父类接口必须确保所有子类都可以实现需求,而不是某一个子类。
例如,java中HashMap和LinkedHashMap都是Map的子类。但是HashMap的顺序是随机的,而LinkedHashMap是固定的。当我们需要使用一个map,此map不需要要求key顺序可控的话,我们可以声明:
Map createMap(){
return
new
HashMap();}
但我们要求顺序可控是,如果是这样:
Map createMap(){
return
new
LinkedHashMap();}
上述代码就不太好了,因为HashMap也是Map的一个子类,但是他不能满足我们的需求,所以此处必须声明返回值类型为LinkedHashMap。例如我们在设计接口的方法的时候,如果调用者需要的是一个LinkedHashMap,我们就不能以HashMap类型做接口的声明。
当然里氏替换原则也可以从设计角度出发,他强调我们设计的时候需要确保父类定义了的时候,就应该覆盖到这个接口抽象出的业务的所有方法,而不需要他的子类再添加额外的扩展,同时各个子类也都该实现父类中的所有接口,只有这样才能保证我们设计出的东西是可扩展的。
开闭原则讲究扩展,里氏替换原则可以确保通过继承这种方式的扩展是可行的,否则就无法使用继承去扩展程序了。
例如:我们使用模板模式,做了一个类作为父类算法模板,一个子类继承了这个模板,并且顺利地完成了运行;但是另一个子类也继承了模板类,却无法运行,最终发现程序无法确保所有继承模板的子类可以替换父类,这就是个失败的模板模式。
从面相对象的角度来说,里氏替换原则是子类可以替代父类,但是从面相组件的角度看,其实是确保组件的api是完整的、不变的,子类和外界也是完全解耦的,只有这样我们开发出的扩展才能在不破坏原有框架的基础上运行。
3.依赖倒置原则
这个原则也是讲究解耦,他指的是让高层模块不要依赖低层模块。这是个纯粹的面向接口,面向模块开发思路了,因为面向对象而言,各个对象自己的东西和外界是解耦的,因为封装特性把它们自己的属性都封装起来了,所以是不会和其他对象有耦合关系的(如c++的友元除外);但是各个对象仍然是相互耦合的,最强的耦合就属于继承耦合了,对象组合起码还是轻耦合,继承是个高耦合呀。依赖倒置就是让各个对象耦合度降低,高层模块不能继承底层模块,需要底层的东西也是外界注入而不是自己创建得到;同时调用的时候也是使用接口调用,而不是依赖具体实现,并且因为是接口调用,具体实现模块可以被任意替换了。
这样做就可以降低各个模块的耦合,也可以确保里氏替换原则的实现。实现里氏替换原则有什么用?当然是可以方便扩展了。
456.职责单一原则、接口隔离原则、最小知道原则(迪米特原则)
这几个原则很像,就放到一起说吧。这几个类都是在强调解耦(当然开闭原则、里氏替换原则、依赖倒置原则也是)。这几个原则基本都是强调解耦,只是站的角度不一样。职责单一原则指的是一个模块(接口)的功能尽量是单一的,这样不同功能的接口就不会耦合在一起了,同时维护起来也方便。接口隔离原则强调每个类继承的接口一定要保证最少,不能继承无用的接口,保证接口隔离原则的前提是先要保证职责单一原则。最后一个最小知道原则指的是模块是所有的依赖都要保证最少,这一点和接口隔离原则有点重复,或者可以说接最小知道原则包含接口隔离原则,同时最小知道原则还有对外界影响最小的意味。这几个原则说的都是类和接口设计要尽量降低耦合的问题。
总结:和设计模式的关系
简单介绍了一下这几大基本原则,再说说我对于他们和设计模式的理解。我们在学习设计模式的时候,有没有想过为什么要学习这个,学习了设计模式有什么好处?我在工作中经常发现很多经验欠缺的程序员,为了学习设计模式而学习设计模式,为了使用设计模式而使用设计模式,而有经验的程序员则不会这样。其实程序员开发的每一个程序都是从需求出发的,只有搞清楚我们一个项目的根本需求才有使用设计模式的意义。
六大原则中,最重要的肯定就是开闭原则了,我对开闭原则的理解是,你无须在每个细节上都要做到对扩展开放,对修改关闭,而是应该为了面对扩展而扩展。当有这种需求的时候,例如一个项目业务、算法可能会有重大的变化,或者本身开发的就是一个组件,这是才需要扩展,而扩展的时候才应该使用设计模式来实现这种需求,也就是说使用设计模式和我们平时开发一样,都是满足需求。
使用了设计模式不一定能真正地提高代码的结构和可维护性,所以有经验的程序员会按需求而使用设计模式。六大基本原则可以更好地帮我们如何分析,这样才能确定是否使用设计模式。事实上设计模式的使用上我建议无招胜有招,满足项目的额外需求(例如利于扩展、可复用、高可维护性)都是好招,无需管他是什么设计模式。
面向对象六大基本原则相关推荐
- 学习设计模式 - 六大基本原则之开闭原则
设计模式总共有六大基本原则,统称为SOLID (稳定)原则,分别是S-单一职责原则(Single Responsibility Principle), O-开闭原则(Open closed Princ ...
- Java开发的六大基本原则
文章目录 1.单一职责原则 2.开放封闭原则 3.里氏替换原则 4.接口隔离原则 5.依赖倒置原则 6.迪米特原则 设计模式之禅 Java开发六大基本原则 1.单一职责原则 单一职责原则(Single ...
- 学习设计模式 - 六大基本原则之单一职责原则
设计模式总共有六大基本原则,统称为SOLID (稳定)原则,分别是S-单一职责原则(Single Responsibility Principle), O-开闭原则(Open closed Princ ...
- 学习设计模式 - 六大基本原则之接口隔离原则
设计模式总共有六大基本原则,统称为SOLID (稳定)原则,分别是S-单一职责原则(Single Responsibility Principle), O-开闭原则(Open closed Princ ...
- 面向对象六大原则详解
本文来说下面向对象六大原则 文章目录 概述 单一职责原则 里氏替换原则 依赖倒置原则 接口隔离原则 迪米特法则 开闭原则 六大原则总结 概述 这是设计模式系列开篇的第一篇文章.也是我学习设计模式过程中 ...
- 【设计模式】第一章 面向对象六大原则
第一章 面向对象六大原则 文章目录 第一章 面向对象六大原则 一.指导思想 二.面向对象六大原则 1.单一职责原则 2.开闭原则 3.里氏替换原则 4.依赖倒置原则 5.接口隔离原则 6.迪米特法则 ...
- python设计模式六大原则_学习设计模式 - 六大基本原则之迪米特法则(示例代码)...
设计模式总共有六大基本原则,统称为SOLID (稳定)原则,分别是S-单一职责原则(Single Responsibility Principle), O-开闭原则(Open closed Princ ...
- Java基础学习总结(84)——Java面向对象六大原则和设计模式
面向对象六大原则 在此之前,有一点需要大家知道,熟悉这些原则并不是说你写出的程序就一定灵活.清晰,只是为你优秀的代码之路铺上了一层栅栏,在这些原则的指导下,你才能避免陷入一些常见的代码泥沼,从而让你写 ...
- java 面向对象原则_Java基础:面向对象六大原则
本文主要介绍了面向对象六大原则. 单一职责原则(Single-Resposibility Principle). "对一个类而言,应该仅有一个引起它变化的原因."本原则是我们非常熟 ...
最新文章
- 收藏 | 2019 NLP大全:论文、博客、教程、工程进展全梳理(附链接)
- leetcode算法题--买卖股票的最佳时机含手续费
- Mybatis二级缓存原理
- HD_I Hate It
- js实现获取当前周,过去和未来周的时间段日期
- 是什么门的缩写_干货分享:汽车排气系统部件有什么?出故障都有什么现象?...
- UIAlterController-ios8弹出菜单
- swagger2 配置访问路径_有了Swagger2 再也不用担心API文档的维护了
- 关于mac m1 安装安卓模拟器
- 计算bed区间gc含量,碱基深度等
- Linux gerp 命令使用方法
- 创建 GitHub 个人访问令牌
- 【测试】详解接口测试(2)- HTTP接口用例设计与测试方法(拿B站练手)
- python处理期货数据_用python中的Pandas库实现一个商品期货网格策略
- 京东客服岗位人才考试
- logstash读取kafka所有topics 自动创建es 索引
- iOS及Mac开源项目和学习资料
- JS—随机三个0-9不重复的随机数
- Java生鲜电商平台-技术方案与文档下载
- 【LaTeX 教程】01. LaTeX 简介与安装
热门文章
- 【已解决】WPS2018 从第三页开始插入页眉页码(即前两页不要页眉页码)
- 计算机评分 游戏图形,win7系统评分中图形和游戏图形这两项有什么不同?
- 基于Ubuntu和STM32分析全局变量、局部变量、堆、栈
- JavaScript面试题集锦
- 【Android底层学习总结】2. 安卓系统内核的Bring Up
- ajax基础知识必看篇(黄梦岚)
- xtrabackup备份恢复
- ipad手写笔什么牌子好?最好用的电容笔
- PLC 西门子smart200 锁机 有图片证明分期付款 动态验证码
- mysql 5.6 全文索引_MySql5.6全文索引 及 5.7 中文索引插件ngram