Java设计模式中的七大原则详细讲解
作者:非凡的小笨鱼 发布时间:2021-07-23 15:38:14
设计模式要进行共性与可变性的分析,对共性进行抽象,同时对可变性进行封装,没有完美的设计模式,作为一名开发者要懂得取舍,触类旁通,开发出高内聚、低耦合、灵活性更高的软件产品
1.开闭原则(软件设计第一原则)
定义:一个软件实体应该对扩展开放,对修改关闭,即在不修改源代码的基础上扩展软件功能
本质思想:
以抽象来固定不变的东西(把固定不变的抽出来)
使用具体实现对可变性进行封装/隐藏
面向抽象编程
2.依赖倒置原则
开闭原则是目标,依赖倒置是手段
三层含义:
高层模块不应该依赖于低层模块,两者都应该依赖其抽象(例如一个类的成员变量、方法的入参、返回值不应该是一个具体类,而最好是一个抽象类)
抽象不应该依赖细节(业务代码不关心具体类)
细节应该依赖抽象(业务代码只关心抽象类)
依赖倒置原则的核心就是面向抽象(抽象类或者接口)编程
3.里氏替换原则
定义:在一个软件产品中,父类对象可以出现的地方,都可以替换成它的子类对象,且不能发生错误和异常,里氏替换原则为良好的继承定义了规范
四层含义:
子类必须完全实现父类的抽象方法,但不能覆盖(重写)父类的非抽象方法
子类可以增加自己特有的方法
当子类一定要重写父类的方法时,子类方法的形参(前置条件)要比父类更宽松(例如父类使用HashMap,子类使用Map)
当子类实现父类的抽象方法时,方法的返回值(后置条件)要比父类更加严格
总结:子类可以扩展父类的功能,但是不能去改变父类原有的功能(遵循父类原有的基础特性,进行一系列的行为变化)
4.合成复用原则
定义:在软件复用时,要尽量使用组合/聚合(has a)等关联关系来实现,即组合/聚合优先于继承
如果要使用继承关系,则必须严格遵循里氏替换原则
合成复用原则和里氏替换原则是相辅相成的,两者都是开闭原则的具体实现规范
设计模式用继承对行为变化进行分类,而不是使用继承来复用逻辑
继承破坏了类的封装性,父类的实现细节全都暴露给子类了
父类和子类的耦合性太高,父类的修改直接影响子类
继承是静态的,与IOC动态注入相违背
5.接口隔离原则
定义:使用多个专门的接口,而不是使用单一的总接口;客户端调用者代码不应该依赖它不需要的接口
使用原则:
根据接口隔离原则拆分接口时,首先必须满足单一职责原则
提高高内聚(每个接口都只负责相互独立的部分,方法间都是强相关的)
定制服务
接口设计要有限度(不要让类过于膨胀)
目标:在发生代码变更,接口变更的情况下,尽量做到影响程度最低
6.迪米特法则
规则:一个类应该尽量少的对其他类相互作用(依赖/调用)
解释:只与直接朋友(私有成员变量、方法入参、new的对象)进行通信,间接朋友:调用直接朋友的方法获取到的对象
目的:让类之间解耦,提高类的复用性,当其他类发生变更的时候,对这个类的影响才最小
缺点:过于严格的遵守此原则,会导致系统产生大量透明的小方法,需要在朋友数量和小方法之间进行权衡
通过下面的例子加深理解,Person类想调用Stranger类执行一些逻辑
public class Person {
private Friend friend = null;
// 遵循迪米特法则
// 将Stranger类封装/隐藏了,Person类不知道Stranger类的存在
// 但是Friend类产生了callStrangerDoSomething这个透明的小方法
public void right(){
friend.callStrangerDoSomething();
}
// 不遵循迪米特法则
// 与Stranger类耦合了
public void wrong(){
Stranger stranger = friend.getStranger();
stranger.doSomething();
}
}
7.单一职责原则
单一职责原则要求一个接口或类只有一个原因引起变化(职责的范围因人而异)
一个接口或一个类只负责一件明确的事,负责的事情越少越好
如果其他类依赖了一个包含多个职责的类,也会将不需要的职责包含进来,也违反了迪米特法则
来源:https://blog.csdn.net/a347635191/article/details/121960915
猜你喜欢
- 前言本文介绍在spring mvc中非常重要的注解@ModelAttribute.这个注解可以用在方法参数上,或是方法声明上。这个注解的主要
- Reflections通过扫描classpath,索引元数据,并且允许在运行时查询这些元数据。使用Reflections可以很轻松的获取以下
- 集成使用1、添加 gradle 依赖implementation "com.ctrip.framework.apollo:apol
- System.out.print("\b") 会在控制台下往回删掉一个字符,如果你想回删多个字符就打印多个 "
- 什么是FTPFTP(File Transfer Protocol)是TCP/IP网络上两台计算机传送文件的协议,使得主机间可以共享文件.可以
- @pathvariable与@requestparam碰到的一些问题一、@pathvariable可以将 URL 中占位符参数绑定到控制器处
- 由于众所周知的原因,maven的库在中国大陆非常慢。我在百度上搜到的大部分文章都是直接在~/.m2/settings.xml 加入以下内容&
- 一、TimeZone 简介TimeZone 表示时区偏移量,也可以计算夏令时。在操作 Date, Calendar等表示日期/时间的对象时,
- 一、说明Boost.MPI 提供了 MPI 标准(消息传递接口)的接口。该标准简化了并发执行任务的程序的开发。您可以使用线程或通过共享内存或
- BLOB (binary large object),二进制大对象,是一个可以存储二进制文件的容器。在计算机中,BLOB常常是数据库中用来存
- 一、问题描述如果在 SpringBoot 项目中的 application.properties 配置了某个属性(假如属性名为 test.k
- Java虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这个
- 前言WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏
- 现在提起Android开发工具,大多人第一个想到的肯定是Android Studio。谷歌专门为Android开发者推出的这款IDE,以其强
- 传播inbound事件有关于inbound事件, 在概述中做过简单的介绍, 就是以自己为基准, 流向自己的事件, 比如最常见的channel
- 线程可以划分优先级,优先级高的线程得到的CPU资源比较多,也就是CPU优先执行优先级高的线程对象中的任务。设置线程优先级有助于帮助线程规划器
- 前言异步调用几乎是处理高并发,解决性能问题常用的手段,如何开启异步调用?SpringBoot中提供了非常简单的方式,就是一个注解@Async
- Android5.0之后提供了JobService和JobScheduler,用于在稍后的某个时间点或者当满足某个特定的条件时执行一个任务
- 下面是一个AOP实现的简单例子:首先定义一些业务方法:/** * Created with IntelliJ IDEA. 
- 前言本文章接上一篇文章继续谈一谈condition的一些用法。案例上一篇文章我提的一个需求时导入jedis坐标后才能加载该Bean,否则不加