深入设计模式02---深入浅出面向对象思想
【摘要】 前言我们都知道Java是经典的面向对象设计的开发语言,我想大家也都知道面向对象的三大特性:封装、继承、多态,有些还会将抽象也加入并称四大特性,那么你知道这些特性是怎么来的吗? Java又是如何被称为面向对象的语言呢?请您带着问题我和一起学习本篇----深入面向对象 正文 简介面向对象设计的目标之一在于提高软件的可维护性与复用性,保证代码的易于扩展与修改, 设计模式在面向对象的基础上诞生,每...
前言
我们都知道Java是经典的面向对象设计的开发语言,我想大家也都知道面向对象的三大特性:封装、继承、多态,有些还会将抽象也加入并称四大特性,那么你知道这些特性是怎么来的吗? Java又是如何被称为面向对象的语言呢?请您带着问题我和一起学习本篇----深入面向对象
正文
-
简介
面向对象设计的目标之一在于提高软件的可维护性与复用性,保证代码的易于扩展与修改, 设计模式在面向对象的基础上诞生,每一个设计模式都符合一个或者多个面向对象的设计原则,从而保证代码质量。
-
面向对象设计七大原则
面向对象的七大常用原则分别是单一职责原则、开闭原则、里氏转换原则、依赖倒转原则、接口隔离原则、合成复用原则、迪米特法则。
哈哈,是不是看完发现一个也不知道?别方,我们看下他们的原理就会发现在开发中这些原则真的是无处不在。-
七大原则原理
-
单一职责原则: 单一职责原则是指一个对象应该只具备单一的职责,尽可能的将粒度的大小降低,这样可以提高该类的复用性。
嗯? 老铁熟悉不? 这其实对应的也是Java中所说的高内聚,一个类只应当具备一类的功能,不应该具备多种功能让类变的杂乱,一方面是不便于维护,另一方面不便于复用。其实我们如果一直培养着良好的编码习惯,有时候可能你并不知道为什么要这样写,但是他这样写就是优雅,就很nice,现在要是看完这篇文章就能明白那不是凭空产生的了。
举一个最简单的例子,我们平时开发时一般三层架构:Controller、Service、Dao,这一定程度上就是符合单一职责原则的,试想一下,如果我们不保持单一原则,让三层搞到成两层或者一层,那会是一种怎样的场景? -
开闭原则: 软件实体应当对扩展开放,对修改关闭。
看看,这是不是更熟悉了? 为了保证代码的安全性,我们需要将内部的一些属性私有化,对外部提供公开的方法访问扩展,这不就是我们说的封装的一种吗?在开发时,我们尽量将系统设计的更加灵活,可以通过不修改代码的方式来修改系统的一些信息,比如说JDBC连接信息,通过配置文件的方式来配置,开闭原则在很大一部分程度上是指我们在新增一些功能或者修改一些信息的时候无需对已有的代码进行更改。
-
里氏转换原则: 所有引用基类的地方必须能透明的使用其子类对象。
里氏转换原则表明将一个基类对象(即父类)替换为他的子类对象,程序将不会产生任何的错误和异常,反过来则不成立,如果一个软件实体使用的是一个子类对象,那么它不一定能够使用基类对象。这其实不是我们说的多态吗?我们可以声明一个父类型,然后将其对象创建为子类型,这样我们其实就是拿着父类型,其实真正运行的是子类型中的代码,这样可以大大的提高我们代码的灵活程度。
-
依赖倒转原则: 高层的模块不应该依赖于低层的模块,他们都应该依赖于抽象。抽象不能依赖于细节,细节可以依赖于抽象。
这个其实更容易理解,我们平时编码时也都是这样做的,主要针对接口、抽象编程,不针对细节编程,为什么呢?因为当我们需要修改或者增加一个方法时,可以直接新增加一个具体的实现类,这样提高的代码的可维护性,我们修改了这块的代码后,对其他代码块基本上不会造成什么影响,也不需要动其它的代码,这样做扩展性是不是提高了?
依赖倒转原则对代码提供了很多的良好约束:
- 针对接口编程,不要针对实现编程,
- 一个具体的实现类中公开的方法应当只有接口中声明过,不要给出多余的方法,否则会出现无法调用子类增加的方法;
- 在程序中尽量使用抽象层进行编程,将具体的实现类写在配置文件中,如果系统发生变化,只需要对抽象层进行扩展,然后修改配置文件,而无需修改原有系统的代码,这又满足开闭原则;
- 实现依赖倒转原则时要将具体的实现类通过依赖注入的方式将具体的实现类注入到其它对象中,常用的依赖注入有三种:构造注入、设值注入(Setter)与接口注入。接口注入是指在类中设置特殊的方法来给属性设值,参数使用的时抽象型,在运行时再将真实的对象注入,来覆盖父类对象。
-
接口隔离原则: 客户端不应该依赖那些它不需要的接口。
这个其实是指接口的设计应当尽可能的粒度小,高内聚,但又不能太小,否则会造成系统的接口过多从而泛滥,如: 我们设计一个接口里面包含三个方法,然后我有一个实现类需要实现该接口的一个方,但是我不得不将其它两个方法也给实现了,就算是null也要实现,因为接口的粒度在这里放着,如果接口粒度再小一些的话,那么我可以更灵活的使用,需要哪个实现哪个,这样就不必去是实现不需要的方法了,从而不去依赖不需要的接口。(补充: 接口有的地方指方法,有的地方指我们所说的interface) -
合成复用原则: 优先使用组合而不是继承来达到复用的目的。
这个就比较容易理解了,像我们常用的@Autowirde是干啥的?这就是一种组合,将对象作为当前对象的一个属性,从而复用代码,为什么说要尽量使用这种不使用继承呢? 想一下,如果通过继承的方式进行复用,那不就破坏了基类的封装性了吗?所有的实现细节都被子类继承了,而且这种方式也不够灵活多用,因此我们应当尽量满足组合复用(当然不是所有哈,如果两个类如狗、哈士奇,那么我们可以让哈士奇继承狗类实现复用,因为他们是有一定的关系的) -
迪米特法则: 每一个软件单位对其它单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位。
一个对象不能和“陌生人”进行交互,只能和“朋友”直接进行通信。
其朋友包括以下几类:
1) 当前对象本身
2) 以参数形式传入到当前对象方法中的对象
3) 当前对象的成员对象
4) 如果当前对象的成员对象是一个集合,那集合中的元素也都是朋友
5) 当前对象所创建的对象
-
-
-
补充与小结
- 面向对象设计原则再软件开发中可以大幅度的提高软件代码的质量;
- 每个设计模式都遵守着一个或多个面向对象设计原则
好了,其实读完本篇我相信大家肯定会有一定的收获了(反正对于一些不怎么爱读书的面试官我们是可以虐一虐了),革命尚未成功,同志仍需努力呀!
这篇博客留下一个作业题(书上的题),大家可以思考下,还是有点意思的:
如上图所示,我们发现到后来我们如果想增加一种新的颜色的笔,都需要增加很多的子类,如增加一种绿色的笔,则每种大小都需要增加一种绿色的笔,系统中类的个数会急剧增加,现在根据依赖倒转原则和合成复用原则对该方案进行重构,请设计。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
作者其他文章
评论(0)