这两个星期开始系统地学习设计模式相关的知识,对每一个原则或者设计模式主要从下面几点分析学习:

  • 定义:简单地描述其作用
  • 解决问题:说明该原则或设计模式解决什么限制条件下的问题。
  • 结构图:绘制相关例子的UML机构图。
  • 代码示例:通过一个例子解释该模式的实现方法。
  • 优缺点:该模式的局限性。

参考资料:

此次学习主要依赖于下面两个技术网站:

设计模式Java版

Java学习助手

文章中出现的图、代码等大部分出自上述两个参考资料,不作为本人的产物。

单一职责原则(Single Responsibility Principle)

定义:

一个类只负责一个功能领域的职责;换句话说,就一个类而言,应该只有一个引起它变化的原因。

注意:

  • 职责扩散是单一职责的挑战,应在其扩散到不可控制之前进行代码重构。
  • 只有在逻辑足够简单或者方法数量足够少,才能够违反单一职责
  • 单一职责的优点主要是:降低类的复杂度,提高类的可读性和可维护性。

例子:

重构前:

重构后:

  • 在CustomerDataChart中定义了多种功能,例如数据库连接、查询顾客、显示图标多个职责。
  • 可以将其进行分解成三个类,分别负责不同的职责。

开闭原则(Open-Closed Principle)

定义:

软件实体应该对扩展开放,对修改关闭。

注意:

  • 抽象化设计是开闭原则的关键:用抽象类构架框架,用实现扩展细节。
  • 其它原则和设计模式的整体概括,该原则是主要目标。

例子:

重构前:

重构后:

  • 先前使用type作为显示图类型的判断因子,如果新增一种图,则需要修改ChartDisplay类,违反了向修改封闭的原则。
  • 重新构建一个抽象类AbstractChart类,所有图像显示都需继承实现抽象类,如果有新的显示类只需要扩展一个新类,而不需要修改ChartDisplay类,符合向扩展开放的原则。
  • 这个重构同时也符合依赖倒置的原则,使客户端程序不需要依赖具体实现,而是依赖抽象。
  • 但是这个重构需要客户端知道所有显示图像类。

里氏代换原则(Liskov Substitution Principle)

定义:

所有引用基类(父类)的地方必需能够透明地使用子类对象。

注意:

  • 将一个基类替换成其子类,程序不会产生任何错误和异常;反之则不成立。
  • 里氏代换原则要求不能破坏继承体系,具体表现在:
    1. 子类应该实现父类的所有抽象方法,不要覆盖父类的非抽象方法。
    2. 子类可以增加自己特有的方法。
    3. 当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。
    4. 当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。

例子:

重构前:

重构后:

  • 重构前,有大量的代码重复,如果增加新的用户,则需要维护EmailSender。
  • 重构后,利用里氏替换原则,能够使用Customer基类的地方,都可以替换为其子类,方便扩展。

依赖倒置原则(Dependency Inversion Principle)

定义:

抽象不依赖于细节,细节依赖于抽象,针对接口编程。

注意:

  • 在程序代码中传递参数或者关联关系式,尽量引用高层的抽象层类。即:使用接口和抽象类进行变量生命、参数类型生命、方法返回类型生命以及数据类型的转换。
  • 当一个对象和其它对象有依赖关系时,可以利用依赖注入的方法将类之间进行解耦。主要有三种:构造注入,Set方法和接口注入。
  • 上述三个原则之间的关系:开闭是原则,里氏是基础,依赖倒置是手段。

参考资料:

深入理解依赖注入

例子:

重构前:

重构后:

  • 重构前如果需要更改不同的DataConvertor就需要更改CustomerDAO的源码。
  • 重构后可以直接利用配置文件指定哪个类,并不需要修改代码。

接口隔离原则(Interface Segregation Principle)

定义:

使用多个专门的接口,而不是使用功能复杂的单一接口。

注意:

  • 控制接口的粒度,接口不能太小,如果太小会导致系统中接口泛滥,不利于维护;接口也不能太大,太大的接口将违背接口隔离原则,灵活性较差,使用起来很不方便。

例子:

重构前:

重构后:

合成复用原则(Composite Resuse Principle)

定义:

又称为组合/聚合复用原则(Composition/Aggregate Reuse Pinciple),尽量使用对象组合,而不是继承来达到复用的目的。

注意:

  • 组合/聚合可以降低类之间的耦合度,并且不会暴漏类的具体实现细节,称为“黑箱复用”;如果是使用继承机型复用,则会将实现细节暴漏给子类,破会系统的封闭性,如果基类变化,子类也随之变化,不具有灵活性,称为“白箱复用”。
  • 一般来说,如果两个类之间是"Has-A"关系,则使用组合/聚合;如果是"Is-A"关系,则使用继承。

例子:

重构前:

重构后:

迪米特法则

定义:

一个软件实体应当尽可能少地与其它实体发生相互作用。

注意:

  • 可以直接相互的作用包括:

    1. 当前对象本身,this。
    2. 以参数形式传入到当前对象方法中的对象。
    3. 当前对象的成员对象。
    4. 如果当前对象的成员对象是一个集合,那么集合中的元素也都可以直接访问。
    5. 当前对象创建的对象。
  • 如果其它对象有相互耦合的情况,尽量采用第三者来降低耦合。

例子:

重构前:

重构后:

  • 重构前各个实体相互作用关系复杂,不利于项目维护。
  • 重构后将所有实体的操作和调用信息都交由Mediator进行中转,利于软件功能扩展和维护。

Java设计模式 -- 基本原则的更多相关文章

  1. java设计模式系列之设计模式概要(1)

    一.什么是设计模式 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. ...

  2. JAVA设计模式总结之23种设计模式

    上一篇总结了设计模式的六大原则<JAVA设计模式总结之六大设计原则>,这一篇,正式进入到介绍23种设计模式的归纳总结. 一.什么是设计模式                         ...

  3. Java设计模式GOF之6大设计原则

    Java设计模式GOF之6大设计原则原则 1.开闭原则(Open Close Principle) 一个软件实体如类.模块和函数应该对扩展开放,对修改关闭. 开闭原则是面向对象的可复用设计的第一块基石 ...

  4. android java 设计模式详解 Demo

    android java 设计模式详解 最近看了一篇设计模式的文章,深得体会,在此基础我将每种设计模式的案例都写成Demo的形式,方便读者研究学习, 首先先将文章分享给大家: 设计模式(Design ...

  5. java设计模式简介

    设计模式简介: 设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用.设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案.这些解决方案是众多 ...

  6. Java设计模式的6大原则

    Java设计模式的6大原则 1.开闭原则(Open Close Principle) 开闭原则就是说对扩展开放,对修改关闭.在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果.简单来 ...

  7. 学习java设计模式有用吗?懂这六个原则,编程更轻松

    学习java设计模式有用吗?懂这六个原则,编程更轻松 1.开闭原则(Open Close Principle) 开闭原则就是说对扩展开放,对修改关闭.在程序需要进行拓展的时候,不能去修改原有的代码,实 ...

  8. JAVA设计模式(6:单例模式详解)

    单例模式作为一种创建型模式,在日常开发中用处极广,我们先来看一一段代码: // 构造函数 protected Calendar(TimeZone var1, Locale var2) { this.l ...

  9. java设计模式- (1)单例模式

    参加校园招聘的笔试,发现公司都会考一些java设计模式,所以上网查询相关内容,总结常用的几种单例模式. 单例模式(Singleton Pattern)是 Java中最简单的设计模式之一.这种类型的设计 ...

随机推荐

  1. 港真,到底应该选择OA还是BPM?

    越来越多企业意识到流程管理的重要性,但是,选择OA还是BPM,却让他们产生了选择困难症. 一方面,企业皆注重流程的高效运转,最好内外部的业务都能用一个系统来解决.所有流程一天就能上线什么的,那就更好啦 ...

  2. NodeJS使用mysql

    1.环境准备 手动添加数据库依赖: 在package.json的dependencies中新增, "mysql" : "latest", { "nam ...

  3. Linux硬件IO的优化简介

    Linux硬件IO的优化简介 首先简单介绍下有哪些硬件设备如下(由于硬件种类厂家等各种因素我就不在此多做介绍有兴趣的可以自行学习): 1.CPU:中央处理器,是计算机运算控制的核心部件之一,相当于人的 ...

  4. 1199 Problem B: 大小关系

    求有限集传递闭包的 Floyd Warshall 算法(矩阵实现) 其实就三重循环.zzuoj 1199 题 链接 http://acm.zzu.edu.cn:8000/problem.php?id= ...

  5. Mono 3.2.3 TCP吞吐性能测试报告

    在前几天简单地测试了一下Mono 3.2.3 TCP处理的稳定性,有同学问Mono 3.2.3的TCP处理性有怎样,以下是针对Mono 3.2.3TCP在吞吐方面的性能测试.主要测试分两种场分别是连接 ...

  6. jexus5.8.2 linux x64专业版 配置https

    一.环境 1.jexus版本:Jexus/5.8.2.8 Linux专业版 内置mono版本:Mono/4.6.2.7 2.操作系统:centOs7 jexus独立版由于是免安装版并且内置mono,所 ...

  7. APP漏洞扫描用地址空间随机化

    APP漏洞扫描用地址空间随机化 前言 我们在前文<APP漏洞扫描器之本地拒绝服务检测详解>了解到阿里聚安全漏洞扫描器有一项静态分析加动态模糊测试的方法来检测的功能,并详细的介绍了它在针对本 ...

  8. 我设计的ASP.NET笔试题,你会多少呢

    本笔试题考查范围包括面向对象基础.HTML.CSS.JS.EF.jQuery.SQL.编码思想.算法等范围. 第1题:接口和抽象类有何区别? 第2题:静态方法和实例方法有何区别? 第3题:什么是多态? ...

  9. 吐血大奉献,打造cnblogs最新最火辣的css3模板(IE9以下请勿入内) -- 第一版

    一直自己都想给自己的博客打造一个独一无二的皮肤,但是一直没有强劲的动力去完成这件事情.后来凭借着工作上面的需求(涉及到css3),就把自己的博客当成一个最好的试验场地.从而产生了你现在所看到的这个模板 ...

  10. CSharpGL(8)使用3D纹理渲染体数据 (Volume Rendering) 初探

    CSharpGL(8)使用3D纹理渲染体数据 (Volume Rendering) 初探 2016-08-13 由于CSharpGL一直在更新,现在这个教程已经不适用最新的代码了.CSharpGL源码 ...