六大设计原则(Java)

设计模式不是新技术,而是解决方案,是大佬们面对不同的需求场景踩过各种坑之后总结出了的一系列最佳实践;

JAVA设计模式提供六个基本原则,分别是:

开闭原则(OCP) - The Open-Closed Principle
单一职责原则(SRP) - Single Responsibility Principle
里氏替换原则(LSP) - Liskov Substitution Principle
依赖倒置原则(DIP) - Dependency Inversion Principle
接口隔离原则(ISP) - Interface Segregation Principle
迪米特法则(DP) - Demeter Principle

单一职责原则

类的变更的原因应该只有一个,它提出用“职责”和“变化原因”来衡量接口或类设计得是否优良,但是这两个因素都是因项目而异因环境而异的,并没有一个量化的标准;

  • 如果接口的单一职责做的好,一个接口修改只对相应的实现类有影响,对系统的扩展性和可维护性也有很大提高;
  • 除了类与接口之外,方法也同样需要使用单一职责原则,避免方法颗粒度太粗;
  • 类尽量做到单一原则,接口一定要做到单一原则;

比如一个用户的实体

它的用户行为和属性没有分开,应该把用户的信息抽取成一个业务对象,把行为抽取成为一个业务逻辑,修改完成后如图
职责划分之后IUserBo负责用户的属性,IUserBiz负责用户的行为;

****这种类的职责划分很简单,但是在一些复杂的场景就并不是很容易了,单一职责最难划分的就是这儿,一个职责一个接口,但是职责没有一个量化的标准,一个类到底要负责那些这侧,这些职责该怎么细化,细化后是否又要有一个接口或类,相同的职责放到一起,不同的职责分解到不同的接口和实现中去,这个是最容易也是最难运用的原则,关键还是要从业务出发,从需求出发,识别出同一种类型的职责。;

【例】大学学生工作管理程序。

分析:大学学生工作主要包括学生生活辅导和学生学业指导两个方面的工作,其中生活辅导主要包括班委建设、出勤统计、心理辅导、费用催缴、班级管理等工作,学业指导主要包括专业引导、学习辅导、科研指导、学习总结等工作。如果将这些工作交给一位老师负责显然不合理,正确的做 法是生活辅导由辅导员负责,学业指导由学业导师负责,其类图如图

大学学生工作管理程序的类图

里氏替换原则

父类可被子类替换,但反之不一定成立,里氏替换为良好的继承定义了一个规范。比如:

List<> list = new ArrayList<>();

注意:

  • 在类中调用其他类时使用父类或接口,像上面代码中那样,如果不这样说明类的设计已经违背了里氏替换;
  • 如果子类不能完全实现父类方法,应该使用依赖、聚集、组合等关系替代继承;
  • 在实际项目中,使用父类作为参数,传递不同的子类完成不同的业务逻辑;

依赖倒置原则

理解:

- 应该面向接口编程,不该面向实现类编程。

  • 高层模块不应该依赖于底层模块,两者都应该依赖于抽象。抽象不应依赖于细节,细节应该依赖于抽象。
  • 面向实现类编程相当于就事论事,那是正向依赖;
  • 面向接口编程,相当于透过现象看本质,抓住事务的共性,那就是反向依赖,即依赖倒置。
使用:
  • 模块间的依赖通过抽象发生,实现类之间不发生直接依赖关系,依赖关系通过接口或抽象类产生;
  • 每个类尽量都有接口或抽象类
  • 尽量不要覆盖基类的方法

接口隔离原则

接口尽量细化
接口中的方法和属性都是实现类所需要,没有额外无用信息,拆分接口是要满足单子职责原则。
也可以实现多个接口来满足需求,接口隔离原则宗旨是接口的完美复用,接口的内容对于实现来说无冗余代码。
接口要高内聚
尽量少公布PUBLIC方法,接口是对外的承诺,接口越少对系统的开发越有利,变更的风险也越少。比如我要我要下属明天下午一点之前搞一个文件,到时间文件就放到了我的桌子上,具体什么文件怎么写我都不用管。
定制服务
单独为一个个体提供接口,如果一个模块除了已有的接口之外还需要另一个功能,再提供一个单独的服务,而不是把这个服务加到那个接口上。
接口设计有限
不要过多的设计接口

迪米特法则

理解
一个类应该对自己需要耦合或调用的类知道的越少越好,你内部是如何复杂和我都没关系,我就知道你提供这么多public方法,我就调用这么多,其他一概不关心。

*朋友类的定义:出现在成员变量、方法的输入输出参数中的类成为成员朋友类,而出现在方法体内部的类不属于朋友类;
例如下面代码中Teacher的朋友类是GroupLeaderlistGirls不是朋友类:

/**
* 老师让体育委员清点女生数量
**/
public class GroupLeader {//清查女生数量public void countGirls(List<Girl> listGirls){System.out.println("女生数量是:"+listGirls.size());}
}
---------------------------------------------------------------------
public class Teacher {//老师对学生发布命令,清点女生public void commond(GroupLeader groupLeader){List listGirls = new ArrayList();//初始化女生for(int i=0;i<20;i++){listGirls.add(new Girl());}//告诉体育委员开始执行清查任务groupLeader.countGirls(listGirls);}
}

上面代码应该将女生的初始化放入GroupLeader中,代码修改为:

public class Teacher {//老师对学生发布命令,清一下女生public void commond(GroupLeader groupLeader){//告诉体育委员开始执行清查任务groupLeader.countGirls();}
}
---------------------------------------------------------------------
public class GroupLeader {private List<Girl> listGirls;//传递全班的女生进来public GroupLeader(List<Girl> _listGirls){this.listGirls = _listGirls;}//清查女生数量public void countGirls(){System.out.println("女生数量是:"+this.listGirls.size());}
}

和朋友类之间保持距离
例如我们在安装软件的时候,经常会有一个导向动作,第一步是确认是否安装,第二步确认License,再然后选择安装目录……这是一个典型的顺序执行动作,具体到程序中就是:调用一个或多个类,先执行第一个方法,然后是第二个方法,根据返回结果再来看是否可以调用第三个方法,或者第四个方法,等等,其类图如图
很简单的类图,实现软件安装的过程,其中first方法定义第一步做什么,second方法定义第二步做什么,third方法定义第三步做什么,其实现过程如代码清单5-8所示。


public class InstallSoftware {public void installWizard(Wizard wizard){int first = wizard.first();//根据first返回的结果,看是否需要执行secondif(first>50){int second = wizard.second();if(second>50){int third = wizard.third();if(third >50){wizard.first();}}}}
}

不难发现,InstallSoftware对Wizard 的耦合太高了,需要修改,应该将installWizard方法放入Wizard 中,Wizard 前三个方法改为私有方法,InstallSoftware仅调用Wizard.installWizard()方法。

总结:迪米特法则的核心观念就是类间解耦,弱耦合,只有弱耦合之后,类的复用率才可以提高。
但是解耦是有限度的,在实际使用中需要适度地考虑这个原则。

开闭原则

理解
类、模块和函数应该通过扩展来实现变化,而不是修改已有的代码,
例子
比如模拟书店卖书,类图如下
现在书全部都是原价出售的,如果我想打折,则不能对原有代码进行修改,应该再扩展一个类继承原有的NovelBook,然后覆盖getPrice,OffNovelBook.getPrice()为打折价格


开闭原则是最基础的一个原则,前面五个原则就是指导设计的工具和方法,而开闭原则才是精神领袖。

使用:
通过接口或抽象类可以约束一组可能变化的行为,并且能够实现对扩展开放。

总结

软件设计最大的难题就是应对需求的变化,但是纷繁复杂的需求变化又是不可预料的。我们要为不可预料的事情做好准备,这本身就是一件非常痛苦的事情,但是大佬们还是给我们提出了6大设计原则以及23个设计模式来“封装”未来的变化。我们可以灵活运用这些东西来解决我们的需求。

【设计模式】一:六大基本原则详解相关推荐

  1. python六大数据类型详解

    python 六大数据类型详解 文章目录 python 六大数据类型详解 数据类型简介 Number(数值) String(字符串) Python字符串的45个方法详解 一.大小写转换 01.capi ...

  2. 设计模式之模板方法模式详解

    设计模式之模板方法模式详解 概述 在面向对象程序设计过程中,程序员常常会遇到这种情况:设计一个系统时知道了算法所需的关键步骤,而且确定了这些步骤的执行顺序,但某些步骤的具体实现还未知,或者说某些步骤的 ...

  3. 设计模式之门面模式详解

    设计模式之门面模式详解 文章目录 设计模式之门面模式详解 一.什么是门面模式 二.门面模式的应用场景 三.门面模式的角色组成 四.门面模式通用写法 五.门面模式在业务中的应用 六.门面模式优缺点 一. ...

  4. android小气泡提示,小气泡六大常见问题详解!

    原标题:小气泡六大常见问题详解! 1.小气泡肌肤深层清洗多久做一次?常常清洗会不会对肌肤让肌肤变薄? 答:人体肌肤角质在17日-28日的周期会主动坠落,跟着年纪的增长会留在肌肤上,是肌肤昏暗的因素,因 ...

  5. 设计模式——模版方法模式详解(论沉迷LOL对学生的危害)

    0. 前言 写在最前面,本人的设计模式类博文,建议先看博文前半部分的理论介绍,再看后半部分的实例分析,最后再返回来复习一遍理论介绍,这时候你就会发现我在重点处标红的用心,对于帮助你理解设计模式有奇效哦 ...

  6. 设计模式之桥接模式详解

    设计模式之桥接模式详解 文章目录 设计模式之桥接模式详解 一.什么是桥接模式 二.桥接模式的应用场景 三.桥接模式的角色组成 四.桥接模式通用写法示例 五.桥接模式优缺点 一.什么是桥接模式 桥接模式 ...

  7. 数据链路层六大协议详解

    数据链路层六大协议详解 一些假设 1.无限制的单工协议(乌托邦协议) 五点假设 发送方 接收方 接受方 2.单工停-等协议 3.有噪声信道的单工协议 本文图片截取自 学堂在线-华南理工大学的计算机网络 ...

  8. 设计模式之策略模式详解

    设计模式之策略模式详解 概述 先看下面的图片,我们去旅游选择出行模式有很多种,可以骑自行车.可以坐汽车.可以坐火车.可以坐飞机. 作为一个程序猿,开发需要选择一款开发工具,当然可以进行代码开发的工具有 ...

  9. java中的装饰模式讲解,java 中设计模式(装饰设计模式)的实例详解

    搜索热词 java 中设计模式(装饰设计模式)的实例详解 应用场景: 在不对原有对象类进行修改的基础上,给一个或多个已有的类对象提供增强额外的功能. 我觉得可以从字面理解,装饰,装饰房子.房子可以看成 ...

最新文章

  1. 2022-2028年中国液化石油气(LPG)行业投资分析及前景预测报告
  2. 【图论专题】欧拉路径和欧拉回路
  3. 是谁“偷吃”了硬盘中的3GB空间
  4. 【Bit-Z新起点,坚守与突破】
  5. chrome扩展程序_如何创建Chrome扩展程序
  6. java学习(43):值参数传递
  7. Vue3 --- axios 简单封装APi
  8. 内蒙古一级计算机考试时间2015,2017年内蒙古计算机一级考试报名时间
  9. Hbase实用技巧:全量+增量数据的迁移方法
  10. Pytest框架教程(一)
  11. 探索大神科比,30000多次投篮数据,有好玩的发现
  12. PGP加密解密QQ邮箱邮件
  13. tomcat6到tomcat9解压版(64位)随意下载
  14. 腾讯AI Lab开放文本理解系统TexSmart,让AI想得更深更广
  15. Ant Design 编写登录和注册页面
  16. LS1046A 启动流程分析
  17. 什么是冷备份和热备份
  18. == 和 ===区别
  19. maps google android版,google maps中文安卓版
  20. redis 实现直播聊天(后台逻辑)

热门文章

  1. iptables实战演练
  2. Json代码实战演练
  3. 数据结构与算法基础Day2
  4. EFM32G232F64时钟树
  5. 2020年,拒绝划水,如何规划前端学习新路径?
  6. 安全模式怎么更改计算机用户,电脑怎么关闭安全模式步骤详解
  7. 调整字体间距属性和文字换行属性
  8. 【最新】2021自动化测试面试宝典1000题
  9. cocos2d-x的初步学习二十三之模仿微信打飞机二
  10. SpringCloud(完结)