单一职责

原则的定义是:应该有且仅有一个原因引起类的变更。

  单一职责原则有什么好处:

    类的复杂性降低,实现什么职责都有清晰明确的定义;
    可读性提高,复杂性降低,那当然可读性提高了;
    可维护性提高,可读性提高,那当然更容易维护了;
    变更引起的风险降低,变更是必不可少的,如果接口的单一职责做得好,一个接口修改只对相应的实现类有影响,对其他的接口无影响,这对系统的扩展性、维护性都有非常大的帮助。

  单一职责原则最难划分的就是职责。一个职责一个接口,但问题是“职责”没有一个量化的标准,一个类到底要负责那些职责?这些职责该怎么细化?细化后是否都要有一个接口或类?这些都需要从实际的项目去考虑.

  对于接口,我们在设计的时候一定要做到单一,但是对于实现类就需要多方面考虑了。生搬硬套单一职责原则会引起类的剧增,给维护带来非常多的麻烦,而且过分细分类的职责也会人为地增加系统的复杂性。本来一个类可以实现的行为硬要拆成两个类,然后再使用聚合或组合的方式耦合在一起,人为制造了系统的复杂性。所以原则是死的,人是活的,这句话很有道理。

  单一职责适用于接口、类,同时也适用于方法,什么意思呢?一个方法尽可能做一件事情,比如一个方法修改用户密码,不要把这个方法放到“修改用户信息”方法中。

  对于单一职责原则,我的建议是接口一定要做到单一职责,类的设计尽量做到只有一个原因引起变化。

注意: 单一职责原则提出了一个编写程序的标准,用“职责”或“变化原因”来衡量接口或类设计得是否优良,但是“职责”和“变化原因”都是不可度量的,因项目而异,因环境而异。

里氏替换原则

在面向对象的语言中,继承是必不可少的、非常优秀的语言机制,它有如下优点:
  ❑ 代码共享,减少创建类的工作量,每个子类都拥有父类的方法和属性;
  ❑ 提高代码的重用性;
  ❑ 子类可以形似父类,但又异于父类,“龙生龙,凤生凤,老鼠生来会打洞”是说子拥有父的“种”,“世界上没有两片完全相同的叶子”是指明子与父的不同;
  ❑ 提高代码的可扩展性,实现父类的方法就可以“为所欲为”了,君不见很多开源框架的扩展接口都是通过继承父类来完成的;
  ❑ 提高产品或项目的开放性。
自然界的所有事物都是优点和缺点并存的,即使是鸡蛋,有时候也能挑出骨头来,继承的缺点如下:
  ❑ 继承是侵入性的。只要继承,就必须拥有父类的所有属性和方法;
  ❑ 降低代码的灵活性。子类必须拥有父类的属性和方法,让子类自由的世界中多了些约束;
  ❑ 增强了耦合性。当父类的常量、变量和方法被修改时,需要考虑子类的修改,而且在缺乏规范的环境下,这种修改可能带来非常糟糕的结果—大段的代码需要重构。

定义:所有引用基类的地方必须能透明地使用其子类的对象。

1. 子类必须完全实现父类的方法

注意:在类中调用其他类时务必要使用父类或接口,如果不能使用父类或接口,则说明类的设计已经违背了LSP原则。

2. 子类可以有自己的个性

3. 覆盖或实现父类的方法时输入参数可以被放大

  子类在没有覆写父类的方法的前提下,子类方法被执行了,这会引起业务逻辑混乱,因为在实际应用中父类一般都是抽象类,子类是实现类,你传递一个这样的实现类就会“歪曲”了父类的意图,引起一堆意想不到的业务逻辑混乱,所以子类中方法的前置条件必须与超类中被覆写的方法的前置条件相同或者更宽松。

注意:如果子类不能完整地实现父类的方法,或者父类的某些方法在子类中已经发生“畸变”,则建议断开父子继承关系,采用依赖、聚集、组合等关系代替继承。

4. 覆写或实现父类的方法时输出结果可以被缩小

  这是什么意思呢,父类的一个方法的返回值是一个类型T,子类的相同方法(重载或覆写)的返回值为S,那么里氏替换原则就要求S必须小于等于T,也就是说,要么S和T是同一个类型,要么S是T的子类,为什么呢?分两种情况,如果是覆写,父类和子类的同名方法的输入参数是相同的,两个方法的范围值S小于等于T,这是覆写的要求,这才是重中之重,子类覆写父类的方法,天经地义。如果是重载,则要求方法的输入参数类型或数量不相同,在里氏替换原则要求下,就是子类的输入参数宽于或等于父类的输入参数,也就是说你写的这个方法是不会被调用的,参考上面讲的前置条件。

  采用里氏替换原则的目的就是增强程序的健壮性,版本升级时也可以保持非常好的兼容性。即使增加子类,原有的子类还可以继续运行。在实际项目中,每个子类对应不同的业务含义,使用父类作为参数,传递不同的子类完成不同的业务逻辑,非常完美!

依赖倒置原则

包含三层含义:
 
 ❑ 高层模块不应该依赖低层模块,两者都应该依赖其抽象;
  ❑ 抽象不应该依赖细节;
  ❑ 细节应该依赖抽象。

  高层模块和低层模块容易理解,每一个逻辑的实现都是由原子逻辑组成的,不可分割的原子逻辑就是低层模块,原子逻辑的再组装就是高层模块。那什么是抽象?什么又是细节呢?在Java语言中,抽象就是指接口或抽象类,两者都是不能直接被实例化的;细节就是实现类,实现接口或继承抽象类而产生的类就是细节,其特点就是可以直接被实例化,也就是可以加上一个关键字new产生一个对象。依赖倒置原则在Java语言中的表现就是:
    ❑ 模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生的;
    ❑ 接口或抽象类不依赖于实现类;
    ❑ 实现类依赖接口或抽象类。
  更加精简的定义就是“面向接口编程” —OOD( Object-Oriented Design,面向对象设计)的精髓之一。

  采用依赖倒置原则可以减少类间的耦合性,提高系统的稳定性,降低并行开发引起的风险,提高代码的可读性和可维护性。

注意:设计是否具备稳定性,只要适当地“松松土”,观察“设计的蓝图”是否还可以茁壮地成长就可以得出结论,稳定性较高的设计,在周围环境频繁变化的时候,依然可以做到“我自岿然不动”。

  两个类之间有依赖关系,只要制定出两者之间的接口(或抽象类)就可以独立开发了,而且项目之间的单元测试也可以独立地运行,而TDD( Test-Driven Development,测试驱动开发)开发模式就是依赖倒置原则的最高级应用。

  抽象是对实现的约束,对依赖者而言,也是一种契约,不仅仅约束自己,还同时约束自己与外部的关系,其目的是保证所有的细节不脱离契约的范畴,确保约束双方按照既定的契约(抽象)共同发展,只要抽象这根基线在,细节就脱离不了这个圈圈,始终让你的对象做到“言必信,行必果”。

对象的依赖关系有三种方式来传递:

  1. 构造函数传递依赖对象

  2. Setter方法传递依赖对象

  3. 接口声明依赖对象
    在接口的方法中声明依赖对象, 3.2节的例子就采用了接口声明依赖的方式,该方法也叫做接口注入。

  依赖倒置原则的本质就是通过抽象(接口或抽象类)使各个类或模块的实现彼此独立,不互相影响,实现模块间的松耦合,我们怎么在项目中使用这个规则呢?只要遵循以下的几个规则就可以:
  ❑ 每个类尽量都有接口或抽象类,或者抽象类和接口两者都具备
    这是依赖倒置的基本要求,接口和抽象类都是属于抽象的,有了抽象才可能依赖倒置。
  ❑ 变量的表面类型尽量是接口或者是抽象类
    很多书上说变量的类型一定要是接口或者是抽象类,这个有点绝对化了,比如一个工具类,xxxUtils一般是不需要接口或是抽象类的。还有,如果你要使用类的clone方法,就必须使用实现类,这个是JDK提供的一个规范。
  ❑ 任何类都不应该从具体类派生
    如果一个项目处于开发状态,确实不应该有从具体类派生出子类的情况,但这也不是绝对的,因为人都是会犯错误的,有时设计缺陷是在所难免的,因此只要不超过两层的继承都是可以忍受的。特别是负责项目维护的同志,基本上可以不考虑这个规则,为什么?维护工作基本上都是进行扩展开发,修复行为,通过一个继承关系,覆写一个方法就可以修正一个很大的Bug,何必去继承最高的基类呢?(当然这种情况尽量发生在不甚了解父类或者无法获得父类
代码的情况下。)
  ❑ 尽量不要覆写基类的方法
    如果基类是一个抽象类,而且这个方法已经实现了,子类尽量不要覆写。类间依赖的是抽象,覆写了抽象方法,对依赖的稳定性会产生一定的影响。
  ❑ 结合里氏替换原则使用
    在第2章中我们讲解了里氏替换原则,父类出现的地方子类就能出现,再结合本章的讲解,我们可以得出这样一个通俗的规则: 接口负责定义public属性和方法,并且声明与其他对象的依赖关系,抽象类负责公共构造部分的实现,实现类准确的实现业务逻辑,同时在适当的时候对父类进行细化。

 依赖倒置原则是6个设计原则中最难以实现的原则,它是实现开闭原则的重要途径,依赖倒置原则没有实现,就别想实现对扩展开放,对修改关闭。在项目中,大家只要记住是“面向接口编程”就基本上抓住了依赖倒置原则的核心。

转载于:https://www.cnblogs.com/gpdm/p/5938633.html

设计模式——设计模式之禅day1相关推荐

  1. 图解设计模式-设计模式七大原则

    Java设计模式 设计模式七大原则 设计模式的目的 编写软件过程中,程序员面临来自 耦合性,内聚性以及可维护性,可扩展性,重用性,灵活性等多方面的挑战,设计模式是为了让 **程序(软件)**具有更好的 ...

  2. 设计模式 ----- 设计模式总结

    设计模式 -– 设计模式总结 设计模式系列源码: https://github.com/liloqian/DesiginModeDemo 1.什么是设计模式 模式是指在某情形下,针对某问题的某种解决方 ...

  3. Java设计模式---设计模式概述及七大原则

    网课指路:尚硅谷Java设计模式(图解+框架源码剖析)_哔哩哔哩_bilibili 设计模式介绍         1) 设计模式是程序员在面对同类软件工程设计问题所总结出来的有用的经验, 模式不是代码 ...

  4. 正确的姿势学习设计模式,设计模式必知必会 --- 面试, 提升篇

    目录 引言--- 为何需要设计模式? 学习设计模式不如掌握设计原则 (根据原则慢慢重构自己的设计模式) 依赖倒置原则 开放封闭原则 面向接口编程 封装变化点(核心原则) 抽象稳定点,扩展变化点 单一职 ...

  5. JavaScript 设计模式----设计模式初识

    JavaScript 设计模式----设计模式初识 1. 从设计到模式 2. 设计模式简介 2.1 设计模式类型 2.2 创建型 2.3 结构型 2.4 行为型 3. 设计原则面试题 3.1 面试题一 ...

  6. 设计模式——设计模式之禅day2

    接口隔离原则 接口分为两种: ● 实例接口( Object Interface) , 在Java中声明一个类, 然后用new关键字产生一个实例, 它是对一个类型的事物的描述, 这是一种接口. 比如你定 ...

  7. [设计模式]设计模式之禅关于接口隔离原则

    在讲接口隔离原则之前,先明确一下我们的主角--接口.接口分为两种: ● 实例接口(Object Interface),在Java中声明一个类,然后用new关键字产生一个实例,它是对一个类型的事物的描述 ...

  8. [设计模式]设计模式之禅关于迪米特法则

    迪米特法则(Law of Demeter,LoD)也称为最少知识原则(Least KnowledgePrinciple,LKP),虽然名字不同,但描述的是同一个规则:一个对象应该对其他对象有最少的了解 ...

  9. [设计模式]设计模式之禅关于单例模式

     1 我是皇帝我独苗 自从秦始皇确立了皇帝这个位置以后,同一时期基本上就只有一个人孤零零地坐在这个位置.这种情况下臣民们也好处理,大家叩拜.谈论的时候只要提及皇帝,每个人都知道指 的是谁,而不用在皇帝 ...

最新文章

  1. 如何初始化静态地图?
  2. spring:注解@Resource,实现引用类型的赋值
  3. 机器人学习--F1TENTH弗吉尼亚大学无人驾驶课程
  4. JVM004_字节码指令简介
  5. 【数据结构与算法】带权图最短路径Dijkstra算法
  6. linux备份还原系统程序
  7. 关于某些同行盗用“jeecg”关键词在百度竞价中推广的声明
  8. jdk1.6+Maven
  9. anacodna/python 安装 tensorflow
  10. 没有MsVCp140如何安装MysQl,win10中msvcp140.dll文件如何安装_win10电脑缺少msvcp140.dll文件的安装教程...
  11. 《深入理解并行编程》中文版
  12. 安全认证框架之Shiro详解
  13. 使用RN开发App,引入图标失效问题的解决
  14. 京东自动化签到脚本-京东休闲游戏自动化签到助手
  15. modscan36--my milestone
  16. idea类注释模板快捷键设置
  17. 代写品牌故事-品牌故事如何写才感人
  18. python编程基础-类的使用
  19. 微信企业红包php,微信公众号发红包和企业付款实现方法
  20. 单片机应用系统设计技术——基于51单片机的火灾温度烟雾报警器设计

热门文章

  1. 【机器视觉】 dev_error_var算子
  2. 【Linux】一步一步学Linux——groupadd命令(87)
  3. java画板抽象类_java 中的 抽象方法 抽象类 和 接口有啥瓜葛
  4. mysql 基本配置_MySQL 基本配置
  5. geany搭建python环境_第一章:搭建Python的开发环境
  6. gsp计算机管理系的功能,药博士医药企业GSP管理系统功能介绍
  7. Redis源码剖析(八)链表
  8. oracle使用sqlplus工具命令连接,快速启动oracle服务。
  9. pixhawk position_estimator_inav.cpp思路整理及数据流
  10. 2060 : Minsum Plus(贪心)