单一职责、接口隔离、依赖倒转、里氏替换、开闭原则、迪米特


二、接口隔离原则


1、目的

避免接口过于臃肿

2、定义

客户端不应该依赖它不需要的接口,一个类对另一个类的依赖应该建立在最小的接口上。

3、具体实现

适度细化接口,将臃肿的接口拆分为独立的几个接口。

4、优点

(1)将臃肿庞大的接口分解为多个粒度小的接口,可以预防外来变更的扩散,提高系统的灵活性和可维护性。

(2)接口隔离提高了系统的内聚性,减少了对外交互,降低了系统的耦合性。

(3)使用多个专门的接口还能够体现对象的层次,因为可以通过接口的继承,实现对总接口的定义。

(4)能减少项目工程中的代码冗余。过大的大接口里面通常放置许多不用的方法,当实现这个接口的时候,被迫设计冗余的代码。

5、注意事项和细节

如果接口的粒度大小定义合理,能够保证系统的稳定性;但是,如果定义过小,则会造成接口数量过多,使设计复杂化;如果定义太大,灵活性降低,无法提供定制服务,给整体项目带来无法预料的风险。

三、依赖倒转原则


1、目的

避免需求变化导致过多的维护工作

2、定义

  • 高层模块不应该依赖底层模块,二者都应该依赖其抽象;

  • 抽象不应该依赖细节;

  • 细节应该依赖抽象。

每一个逻辑的实现都是由原子逻辑组成的,不可分割的原子逻辑就是低层模块(一般是接口,抽象类),原子逻辑的组装就是高层模块。在Java语言中,抽象就是指接口和或抽象类,两者都不能被直接实例化。细节就是实现类,实现接口或继承抽象类而产生的类就是细节,可以被直接实例化。

3、具体实现

面向接口编程,使用接口或者抽象类制定好规范和契约,而不去设计任何具体的操作,把展现细节的任务交给他们的实现类去完成。

4、DIP的好处

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

5、DIP的几种写法

(1)接口声明依赖对象;

(2)构造函数传递依赖对象;

在类中通过构造函数声明依赖对象(好比spring中的构造器注入),采用构造器注入。

(3)Setter方法传递依赖对象

在抽象中设置setter方法声明依赖对象(spring中的方法注入)

6、深入理解

依赖倒转原则的本质就是通过抽象使各个类或模块实现彼此独立,不互相影响,实现模块间的松耦合。

在项目中使用这个规则需要以下原则:

(1)每个类尽量都要有接口或抽象类:依赖倒转的基本要求,有抽象才能依赖倒转;

(2)变量的表明类型尽量是接口或者抽象类;

(3)任何类都不应该从具体类派生;

(4)尽量不要重写基类已经写好的方法(里氏替换原则);

(5)结合里氏替换原则来使用:

接口负责定义public属性和方法,并且声明与其他对象的依赖关系;

抽象类负责公共构造部分的实现;

实现类准确的实现业务逻辑,同时在适当的时候对父类进行细化;

一句话,依赖倒转原则就是面向接口编程。


四、里氏替换原则


1、目的

避免系统继承体系被破坏

2、定义

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

3、具体实现

(1)子类可以实现父类的抽象方法,但是不能覆盖父类的非抽象方法;

(2)子类可以增加自己特有的方法;

(3)当子类覆盖或实现父类的抽象方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松;方法的后置条件(即方法的返回值)要比父类更严格。

(4)如果子类不能完整地实现父类的方法,或者父类的一些方法在子类中已经发生畸形,则建议断开继承关系,采用依赖,聚合,组合等关系继承。

4、代码实例

package designMode.advance.principle;

public class Liskov {

public static void main(String[] args) {

A a = new A();

System.out.println(“11-3=” + a.func1(11, 3));

System.out.println(“1-8=” + a.func1(1, 8));

System.out.println(“-----------------------”);

B b = new B();

//因为B类不再继承A类,因此调用者,不会再func1是求减法

//调用完成的功能就会很明确

System.out.println(“11+3=” + b.func1(11, 3));//这里本意是求出11+3

System.out.println(“1+8=” + b.func1(1, 8));// 1+8

System.out.println(“11+3+9=” + b.func2(11, 3));

//使用组合仍然可以使用到A类相关方法

System.out.println(“11-3=” + b.func3(11, 3));// 这里本意是求出11-3

}

}

//创建一个更加基础的基类

class Base {

//把更加基础的方法和成员写到Base类

}

// A类

class A extends Base {

// 返回两个数的差

public int func1(int num1, int num2) {

return num1 - num2;

}

}

// B类继承了A

// 增加了一个新功能:完成两个数相加,然后和9求和

class B extends Base {

//如果B需要使用A类的方法,使用组合关系

private A a = new A();

//这里,重写了A类的方法, 可能是无意识

public int func1(int a, int b) {

return a + b;

}

public int func2(int a, int b) {

return func1(a, b) + 9;

}

//我们仍然想使用A的方法

public int func3(int a, int b) {

return this.a.func1(a, b);

}

}

五、开闭原则


1、目的

提高扩展性、便于维护

2、定义

对扩展开放(对提供方),对修改关闭(对使用方)。

当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现。

开闭原则是面向对象设计中最基础的设计原则,它指导我们如何建立稳定灵活的系统,开闭原则只定义了对修改关闭,对扩展开放。

因为抽象灵活性好,适应性广,只要抽象的合理,可以基本保证架构的稳定。而软件中易变的细节,我们用从抽象派生的实现类来进行扩展,当软件需要发生变化时,我们只需要根据需求重新派生一个实现类来扩展就可以了,当然前提是抽象要合理,要对需求的变更有前瞻性和预见性。

六、迪米特法则


1、目的

降低类与类之间的耦合度

2、定义

迪米特法则又叫最少知道原则,即一个类对自己依赖的类知道的越少越好,对于依赖的类不管有多复杂,都尽量将逻辑封装在类的内部,对外除了提供public方法,不泄漏任何信息。

更简单的说法:只与直接朋友通信。

直接朋友:每个对象都会与其它对象有耦合关系,耦合的方式有很多,依赖、关联、组合、聚合等。我们称出现在成员变量,方法参数,方法返回值中的类称为直接朋友,而出现在局部变量中的类不能称为直接朋友,也就是说,陌生的类不要以局部变量的形式出现在类的内部。

3、注意事项和细节

(1)在类的结构设计上,尽量降低类成员的访问权限;

(2)在类的设计上,优先考虑将一个类设计成不变类;

(3)在类的引用上,将引起其他类的次数降到最低;

(4)不暴露类的属性成员,而应该提供相应的访问器(getter、setter);

(5)谨慎使用序列化(serializable)功能;

过分的使用迪米特原则,会产生大量这样的中介和传递类,类之间需要通信就通过第三方转发的方式,就会造成系统的不同模块之间的通信效率降低、使系统的不同模块之间不容易协调等缺点,同时大大增加了系统的复杂度。所以在釆用迪米特法则时需要反复权衡,确保高内聚和低耦合的同时,保证系统的结构清晰。

4、代码实例

下面代码违反了迪米特法则,我平时就这么写的。。。

package designMode.advance.principle;

import java.util.ArrayList;

import java.util.List;

public class Demeter {

public static void main(String[] args) {

//创建了一个 SchoolManager 对象

SchoolManager schoolManager = new SchoolManager();

//输出学院的员工id 和 学校总部的员工信息

schoolManager.printAllEmployee(new CollegeManager());

}

}

//学校总部员工类

class Employee {

private String id;

public void setId(String id) {

this.id = id;

}

public String getId() {

return id;

}

}

//学院的员工类

class CollegeEmployee {

private String id;

public void setId(String id) {

this.id = id;

}

public String getId() {

return id;

}

}

//管理学院员工的管理类

class CollegeManager {

//返回学院的所有员工

public List getAllEmployee() {

List list = new ArrayList();

for (int i = 0; i < 10; i++) { //这里我们增加了10个员工到 list

CollegeEmployee emp = new CollegeEmployee();

emp.setId("学院员工id= " + i);

list.add(emp);

}

return list;

}

}

//学校管理类

//分析 SchoolManager 类的直接朋友类有哪些 Employee、CollegeManager

//CollegeEmployee 不是 直接朋友 而是一个陌生类,这样违背了 迪米特法则

class SchoolManager {

//返回学校总部的员工

public List getAllEmployee() {

List list = new ArrayList();

for (int i = 0; i < 5; i++) { //这里我们增加了5个员工到 list

Employee emp = new Employee();

emp.setId("学校总部员工id= " + i);

list.add(emp);

}

return list;

}

//该方法完成输出学校总部和学院员工信息(id)

void printAllEmployee(CollegeManager sub) {

//分析问题

//1. 这里的 CollegeEmployee 不是 SchoolManager的直接朋友

//2. CollegeEmployee 是以局部变量方式出现在 SchoolManager

//3. 违反了 迪米特法则

//获取到学院员工

List list1 = sub.getAllEmployee();

System.out.println(“------------学院员工------------”);

for (CollegeEmployee e : list1) {

System.out.println(e.getId());

}

//获取到学校总部员工

List list2 = this.getAllEmployee();

System.out.println(“------------学校总部员工------------”);

for (Employee e : list2) {

System.out.println(e.getId());

}

}

}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
img

更多:Java进阶核心知识集

包含:JVM,JAVA集合,网络,JAVA多线程并发,JAVA基础,Spring原理,微服务,Zookeeper,Kafka,RabbitMQ,Hbase,MongoDB,Cassandra,设计模式,负载均衡,数据库,一致性哈希,JAVA算法,数据结构,加密算法,分布式缓存等等

image

高效学习视频

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
img

12897200771)]
[外链图片转存中…(img-Dgb6Oxqu-1712897200772)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-bZ1I5djh-1712897200772)]

更多:Java进阶核心知识集

包含:JVM,JAVA集合,网络,JAVA多线程并发,JAVA基础,Spring原理,微服务,Zookeeper,Kafka,RabbitMQ,Hbase,MongoDB,Cassandra,设计模式,负载均衡,数据库,一致性哈希,JAVA算法,数据结构,加密算法,分布式缓存等等

[外链图片转存中…(img-nsLYFUX7-1712897200773)]

高效学习视频

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-GprmYtbP-1712897200773)]

  • 27
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值