当前位置: 首页 > news >正文

软件架构设计原则

在这里插入图片描述

开闭原则

  开闭原则(Open-Closed Principle,OCP)是指一个软件实体,应该对扩展的开放的,对于修改是关闭的。开闭就是指拓展与修改两个行为。什么意思呢?就是说对于一个Java对象来讲,你可以去继承它方法和属性,对继承类进行拓展,但是不可以直接修改它的方法和属性。这样提高了软件系统的可复用性和可维护性。

  开闭原则作为面向对象设计的基本原则,直接对接了面向对象的三大特性,继承、封装、多态。可以在不修改源代码的情况下实现新增功能。

  简单的举个例子,宠物 Pets,有名字、年龄大小、毛色等属性

public class Pets{private String name;private Integer age;private String color;
}

  整个宠物圈,可能有小猫、小狗、小猪等等一些宠物。例如下面来建立一个一个猫的宠物类型,它除了上面的属性之外,还有一个动作就是吃。这个时候可以继承Pets类然后给小猫一个吃的方法。

public class CatPets extends Pets{public void eat(){}
}

  对于小狗、小猪也是以同样的方式创建,这个时候我们可以知道,猫也有很多的更细的分类。这个时候我们对于每个猫的修改就是继承CatPets进行更加细致的分类了。而不是去修改顶层的Pets类型。

依赖倒置原则

  依赖倒置原则(Dependence Inversion Principle,DIP)是指在设计代码结构的时候,高层次的模块不应该依赖低层次的模块,二者都应该依赖其抽象。抽象内容不应该依赖具体的细节性的内容。通过依赖倒置,可以减少类对象与类对象之间的耦合性。这样可以提高系统的稳定性,提高代码的可读性和可维护性,并且能够降低修改程序所造成的后续风险。
  拿上面的宠物的例子来讲,先创建一个人的对象Person类

public class Person{// 养猫public void keepCarPets(){}// 养狗public void keepDogPets(){}
}

  这个人非常喜欢养宠物,他养了猫和狗两种宠物。但是如果这个时候他看到一个宠物猪也比较好,他想养宠物猪怎么去做呢?就需要在Person类中增加 keepPigPets()的方法。这样的做法就是修改了高层次的代码,如果这样修改的话每次他想养新的宠物的时候,就要去新增一个方法,如果修改的内容较多的话,就会是一个非常复杂的工程了。
  这个时候就可以通过下面这种方式来实现了

public interface KeepPets{public void keeyPets(Pets pets){}
}

  定义一个接口类,然后这个人继承这个接口类,接口类中有一个方法就是keepPets(Pets pets)养宠物,这个时候,如果想去养新的宠物的时候就可以通过如下的方式实现了

public class Person interface KeepPets{public void keeyPets(Pets pets){}
}
public class Test{public static void main(String[] args){Person person = new Person();person.keeyPets(new CatPets());person.keeyPets(new DogPets());person.keeyPets(new PigPets());}}

  这个时候就可以看到,无论想养多少宠物的时候都不会再害怕了。只需要告诉养什么就可以了,而不需要修改底层的代码。实际上这就是依赖注入。注入的方式还有很多,通过构造函数注入,通过Setter方法注入等方式。

  通过构造器注入的时候,在调用的期间每次都会创建新的实例,如果是一个全局单实例的对象话就只能通过Setter方式进行注入。

  切记:以抽象为基准比以细节为基准搭建起来的架构要稳定很多,因此在拿到需求之后一定要面向接口进行编程,先设计顶层再设计细节。

单一职责原则

  单一职责(Simple Responsibility Pinciple,SRP)是指不要存在多余一个导致类变更的原因。什么意思呢?假设我们又一个类负责的是两个功能,一旦发生需求变化的时候,修改其中一个功能就会导致另一个功能也发生了故障。这样一来,一个类就存在了两个导致类变更的原因。那么如何解决这个问题呢?解耦。后期需求变更之后相互之后不会产生影响。这样的设计方式可以大大降低类的复杂度,提高可读性,提高系统的可维护性,降低了变更代码之后引起的风险。总体来说就是一个类只负责一个功能。

接口隔离原则

  接口隔离原则(Interface Segregation Principle,ISP)是指用多个专门的接口,而不是单一的使用一个接口。客户端不应该依赖他不需要的接口。在实现这个设计原则的时候需要注意以下的几点。

  • 一个类对另一个类的依赖应该建立在最小的接口上
  • 建立一个单一的接口,不需要一个庞大的总接口
  • 尽量让接口细化,减少接口中的方法,但并不是越少越好。

  接口隔离原则符合常说的高内聚、低耦合的设计思想。可以让类具有更好的可读性、可扩展性和可维护性。在设计接口的时候需要花点时间去思考,需要的业务模型,包括以后可能发生的变化的预判。

迪米特原则

  迪米特原则(Law of Demeter LoD)是指一个对象应该对其他对象保持最小的了解。所以又叫最少知道原则。尽量降低类与类之间的耦合度。该原则主要强调:只和自己的朋友交流,不要和陌生人说话。出现在成员变量、方法和输入、输出参数中的类都可以称为朋友类,而出现在方法体内部的类则不属于朋友类。

  例如,你作为一个学校的校长,你想要知道某个班的学生有多少人,你不需要亲自去数,而是只需要找到对应班级的班主任即可。如下

  有一个学生类Student

public class Student{}

  有一个班主任类

public class HeadMaster{public Integer countStudent(List<Student> studentList){return classStudent.size();}
}

  一个校长类

public class SchoolMaster{public Integer studentNumber(HeadMaster headMaster){List<Student> studentList = new ArrayList<>();headMaster.countStudent(studentList);}
}

  这个时候就实现了,校长与老师的关联,校长并不需要直接与每个学生发生关联。

里式替换原则

  里式替换原则(Liskov Substitution Principle,LSP)是指如果每个类型为T1的对象O1,都有类型为T2的对象O2,使得以T1定义的所有程序P在所有的对象O1都替换成O2的时候,程序P的行为没有发生变化,那么类型T2就可以直接转换为T1。

  这个定义看上去有点抽象,简单的理解为,一个软件实体如果适用于一个父类,那么一定使用与其子类,所有的引用了父类的地方必须能够透明的使用其子类对象,子类对象能够替代父类对象,但是程序的逻辑不变。可以简单的理解为子类可以继承父类的功能,但不能改变父类原有的功能。这也就是很多的地方会有一个注解@Override 的原因。

  使用里式替换原则有如下的有点

  • 1、约束继承泛滥,是开闭原则的一种体现
  • 2、加强程序的健壮性,同时变更时可以做到非常好的兼容性,提高程序的可维护性,降低了需求变更的时候引入的风险。

合成复用原则

  合成复用原则(Composite/Aggregate Reuse Principle,CARP)是指在开发过程中尽量使用对象组合、聚合而不是通过继承关系达到可复用的目的。这样可以使得系统更加灵活,降低类与类之间的耦合度,一个类的变化不会对其他类产生影响。

  继承被称为白箱复用,相当于把所有父类的细节都暴露给子类,组合的方式则被称为黑箱复用。无法获取到类以外的对象的实现细节。但是这一设计需要严格遵守OOP模型。

总结

  能将设计原则结合到自己的项目中,可以极大的提升代码的复用率,降低系统耦合度,提高程序拓展性,为后续的升级迭代打下坚实的基础。


http://www.mrgr.cn/news/34850.html

相关文章:

  • 启动QT时,出现找不到python27.dll的问题报错
  • SQL中的时间类型:深入解析与应用
  • WebRTC项目一对一视频
  • 基于Spring Boot与Redis的令牌主动失效机制实现
  • 320页PDF | 集团IT蓝图总体规划报告-德勤(限免下载)
  • 新日撸java三百行` 新手小白java学习记录 `Day1
  • Java:列表操作
  • C++:类中的特殊内容
  • 基于BeagleBone Black的网页LED控制功能(Flask+gpiod)
  • Vue学习记录之八(局部组件,全局组件,递归组件,动态组件)
  • C++学习笔记----8、掌握类与对象(一)---- 对象中的动态内存分配(1)
  • Redis 的 Java 客户端有哪些?官方推荐哪个?
  • 末端无人配送产业链
  • MyBatis参数处理
  • JAVA无缝沟通全球国际版多语言语聊系统小程序源码
  • SOMEIP_ETS_127: SD_Multicast_FindService
  • Electron 更换窗口图标、exe执行文件图标
  • 工博会蓝卓逛展攻略
  • Pandas DataFrame 对象的基本操作
  • Reis数据库及key的操作命令汇总
  • 动态倒计时在 Vue 3 中的实现
  • 关系型数据库 - MySQL II
  • 振弦式渗压计智慧水利工程 适用恶劣环境有保障
  • 解密云WAF的核心功能!为企业保驾护航的关键技术
  • Warrior Pack Super Bundle 人物战斗动画捆绑包
  • 等位基因与碱基:异同点解析