博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
设计模式--SOLID四大原则,KISS和YAGNI笔记
阅读量:4029 次
发布时间:2019-05-24

本文共 4448 字,大约阅读时间需要 14 分钟。

单一职责原则:S

1.如何理解(SRP):		一个类只负责完成一个职责的功能,不要设计大而全的类,单一职责原则是为了实现代码的高内聚,低耦合,提高代码的可读性和复用性	2.如何判断一个类是否符合单一职责原则:		不同的应用场景,不同的阶段的需求背景,对同一个类的职责是否单一有不同的判定结果。		我们可以使用以下的小技巧来判断:			1.类中的代码行数,函数或者属性过多			2.类依赖的其他类过多,或者依赖类的其他类过多			3.私有方法过多			4.比较难给一个类起一个合适的名字,起的名字比较笼统,例如:manger类,context类			5.类中大量的方法都是集中操作某一些属性	3.类的职责是否设计的越单一越好呢?		并不是越设计的越单一越好,如果拆分的过细的话,实际上会降低内聚性,也会影响代码的可维护性

对外开放,修改关闭原则:O

1.如何理解:		添加一个功能,应该是通过已有代码的基础上扩展代码,而非修改代码的方法来完成。		注意:			1.开闭原则并非是说完全杜绝修改,而是以最小的修改来完成新功能的开发			2.同样的代码改动,在不同的代码粒度下可能理解的不同	2.如何做到:		我们时刻要具备扩展意识,抽象意识,封装意识。在写代码的时候,我们要多花些时间想想,这段代码在未来可能有哪些需求的变动,如何设计代码,事先留好扩展点,以便未来需求变更的时候,在极小的代码改动下,将新的功能插入到扩展点上。	3.最常用来提高代码扩展性的方法有	多态、依赖注入、基于接口而非实现编程,以及大部分的设计模式(比如,装饰、策略、模板、职责链、状态)

里氏替换原则:L

* 理解:	1.用来指导继承关系中子类如何设计的一个原则,核心:“design by contarct:按照协议来设计”	2.子类完美继承父类的设计初衷,并做了增强	3.子类对象能够替换程序中父类对象出现的任何地方,并且保证原来的程序的逻辑行为不变及正确性不被破坏* 具体体现:	父类定义了函数的“协议”,那么子类可以改变函数的**内部实现逻辑**,但是不能改变函数原有的“约定”		这里的约定包括:			1.父类函数声明要实现的功能,子类必须实现该功能				例:父类实现的函数是按照订单金额排序的,而继承的子类是按照下单时间排序的,这就违反了里氏替换原则			2.对父类定义的输入的数据,输出的数据,异常的约定不能违背				例1(输入):父类能输入任意的整数,而子类只能输入正整数这就违背了原则				例2(输出):父类的函数约定:运行出错的时候返回null,获取数据为空的时候返回空集合,而子类的实现变成了运行出错返回异常,获取数据为空返回null,这就违反了里氏替换原则				例3(异常):父类定义了只会抛出 ArgumentNullException 异常,那么子类必须只能抛出ArgumentNullException异常,其他的异常就违背了原则			3.注释中所罗列的任何特殊说明不能违背				例:父类函数的注释是:用户的提现金额不得超过账户余额,而子类重写函数后,针对vip用户实现提现金额可以大于账户余额。这就违反了里氏替换原则* 与多态的区别:	虽然定义描述和代码实现有点类似,但是他们的关注点是不一样的,多态是面向对象的一大特性,它是一种代码实现的思路。而里式替换是一种设计原则,指导继承关系中子类该如何设计* 判断的小技巧:	拿父类的单元测试去验证子类的代码。如果某些单元测试运行失败,就有可能说明,子类的设计实现没有完全地遵守父类的约定,子类有可能违背了里式替换原则

接口隔离原则:I

* 重点是理解“接口”二字,以下三种的不同的理解	1.“接口理解为一组接口集合”:		可以是某个微服务的接口或者某个类库的接口,如果这部分接口只被部分调用者来使用的话,我们就需要将这部分接口隔离出来,单独给这部分调用者使用,而不强迫其他调用者也依赖这部分不会被用到的接口			例如:				用户的删除接口,我们只希望给后台管理者使用,其他普通用户不能使用,这时候我们就需要把这接口给隔离出来	2.“接口理解为单个api接口或者函数”:		部分的调用者只需要函数中的部分功能,闹我们就需要把这个函数拆分成粒度更小的多个函数,让调用者只依赖它需要的那个细粒度函数			例如:				count()是完成求平均数,最大数,最小数的函数,那么如果有些用户只需要求平均数,不常用到最大数和最小数,那么我们就需要把函数拆分为max(),min(),avg()这三个粒度更小的函数	3.“接口理解为oop的接口”:		那么接口的设计要尽量的单一,不要让接口的实现类和调用者,依赖不需要的接口函数* 接口隔离原则和单一职责原则的区别:	单一职责原则是对类,模块,接口的设计,接口隔离原则相对于单一职责原则,一方面侧重于接口的设计,另一方面思考的角度不同,它提供了一种判断接口的职责是否单一的一个标准:通过调用者如何使用接口来间接的判定,如果调用者只使用部分的接口或者接口的部分功能,那接口的设计就不够单一

依赖反转 D:

# 控制反转:	1.这里的“控制”指的是对程序的执行流程的控制,而“反转”指的是没有使用框架之前,程序员自己控制整个程序的执行。在使用框架之后,整个程序的执行流程可以通过框架来控制。流程额控制从程序员“反转”到了框架	2.它不是具体的实现技巧,而是笼统的设计思想,用于指导框架的设计	3.实现控制反转的方法有很多,例如:模板设计模式方法,依赖注入等(搜集)	4.案例分析:(模板设计的控制反转)		//测试必须实现的接口		public abstract class TestCase {			public voi d run() {				if(doTest()){					System.out.println("Testsucceed.");				}else{					System.out.println("Testfailed.");				}			}			public abstract voi d doTest() ;		}		//测试框架		public class JunitApplication {			private static final List
testCases = new ArrayList<>() ; public static void register(TestCase testCase) { testCases.add(testCase) ; } public static final void main(Stri ng[] args) { for(TestCase case: testCases) { case.run(); } } } //具体测试的类 publi c class UserServi ceTest extends TestCase { @Overri de publi c boolean doTest() { // 主要测试的功能 } }# 依赖注入: 1.它是一种编程的技巧,不通过new()的方式在类的内部创建依赖类的对象,而是将依赖的类对象在外部创建好之后,通过构造函数,函数参数等方式传递(或注入)给类使用 2.这里的依赖类可以定义成接口,基于接口实现而非实现编程 3.它可以实现控制反转 # 依赖注入框架: 1.通过依赖注入框架提供的扩展点,简单配置一下所有需要的类及其类与类之间的依赖关系,就可以实现由框架来自动创建对象,管理对象的生命周期,依赖注入等原本需要程序员来做的事,全都交给框架来实现 2.Spring 框架的控制反转主要是通过依赖注入来实现的# 依赖反转:(依赖倒置) 1.高层的模块不要依赖于底层的模块。高层模块和底层的模块应该通过抽象来相互依赖,除此之外,抽象不要依赖具体的实现细节,但是具体的实现细节依赖抽象 2.这里的高层模块简单来说,在调用链上,调用者属于高层模块,被调用者属于底层模块。 3.跟控制反转有点类似,主要用于指导框架的设计 4.案例分析: 1.Tomcat是javaweb容器,我们编写的web应用程序只要部署在tomcat容器中,便可以被tomcat容器调用执行。 2.这样的话,Tomcat就是高级模块,我们编写的应用程序属于底层模块。 3.Tomcat和应用程序之间并没有直接的依赖关系,两者都依赖于同一个抽象,也就是servlet规范, 4.servlet规范不依赖与具体的tomcat容器和应用程序的实现细节,而tomcat和应用程序依赖于servlet的规范

kiss原则和YAGNI原则:

# Kiss原则:尽量保持代码简单# 代码少并不一定满足KISS原则,我们还是考虑逻辑的复杂度,代码的可读性等# 本身负责的问题,用复杂的方法解决,并不违背kiss原则:	例如:KMP 算法本身具有逻辑复杂、实现难度大、可读性差的特点,但是对于当我们需要处理长文本字符串匹配问题,遇到系统性能瓶颈的时候我们应该考虑使用kmp算法# 同样的代码,在某个业务场景下满足 KISS 原则,换一个应用场景可能就不满足了	我们平时开发使用普通的工具类的时候就可以,但是如果考虑系统系统性能的时候,这时候我们就需要自己实现工具类来提高性能# 如何写出满足KISS原则的代码?	1.不要使用同时可能不懂的技术来实现代码	2.不要重复造轮子,要善于使用已经有的工具类	3.不要过度的优化,不要过度使用一些奇技淫巧(位运算,复杂的if-else)来优化代码,来牺牲代码的可读性#建议:	在开发中,不要过度的设计,其实用简单的方法解决复杂的问题,更能体现一个人的能力#YAGNI原则:不要去设计当前用不到的功能,不要去编写当前用不到的代码	例如:		1.系统暂时使用redis来存储配置信息,以后可能会用到zookeeper,我们就没有必要提前写zookeeper代码,但是我们还是要预留好扩展点,等到需要的时候,再去实现这部分代码		2.我们在项目中不要提前引入不需要依赖的开发包#KISS和YAGNI区别	KISS是“如何做”的问题(尽量保持简单),而YAGNI是“要不要做”的问题(当前不需要就不去做)# 针对什么时候重复造轮子,什么时候应该使用现成的工具类,开源框架?	# 什么时候重复造轮子		1.想学习轮子的原理		2.现有的轮子不能满足性能的需求,也没有好的替代品(因为轮子一般会考虑大而全的问题,这对性能有损耗)		3.小而简单的问题	# 什么时候应该使用现成的工具类,开源框架		对于工作中,应该使用工具类和开源框架,没有必要去自己造轮子,增加了开发成本,增加了开发周期

转载地址:http://txobi.baihongyu.com/

你可能感兴趣的文章
自然语言处理中的Attention机制
查看>>
pbc 的使用
查看>>
luasocket 安装遇到的问题
查看>>
lua读写redis的环境部署
查看>>
Using MIT-Scheme in MacOS X on the Command Line
查看>>
php redis 接口说明
查看>>
cocos2dx使用lua和protobuf
查看>>
lua5.2 可能会遇到的一些错误
查看>>
C语言编译过程
查看>>
stirling formula prove
查看>>
关于数字类型转化为整型的方法
查看>>
PHP 常用正则表达式整理
查看>>
自然计算
查看>>
自然计算时间复杂度杂谈
查看>>
当前主要目标和工作
查看>>
系统菜单
查看>>
路漫漫其修远兮,吾将上下而求索(2)
查看>>
versions mac yosemite 下崩溃的修复
查看>>
github push 出现connection refused 的处理办法
查看>>
Linux配置sendmail实现PHP发送邮件
查看>>