-
高层模块不应该依赖底层模块,两者都应该依赖其抽象
-
抽象不应该依赖细节,细节应该依赖抽象
-
依赖倒转原则的中心思想是面向接口编程
-
依赖倒转原则是基于这样的设计理念: 相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础的架构比以细节为基础的架构要稳定的多。在java当中抽象的是值接口或者是抽象类,细节指的是实现类。
-
使用接口或者抽象类的目的是制定好规范,而不涉及任何具体操作,把展示细节的任务交给他们的实现类来完成
使用的是接口的方式来对类当中的信息进行接收操作
no依赖倒转
接下来可以使用的一种方式是没有使用接口来进行依赖的接收
package com.yt.dependencyInversion.nodependencyInversion;
/**
* @program: designPattern
* @description
* @author: YangTao
* @create: 2024-02-20 21:21
**/
public class NoDependencyInversion {
public static void main(String[] args) {
Person person = new Person();
person.receive(new Email());
}
}
class Email{
public String getInfo(){
return "没有进行依赖倒转";
}
}
class Person{
// 这里只是进行的email邮件的信息的接收操作,没有进行额外的信息接收处理操作
// 当想要继续接收新的邮件方式的情况要对其进行方法的添加操作
// 比如添加的类型信息方式为:QQ,微信
// 还有添加方法来进行扩展的方式
// 这种效果不是很好
public void receive(Email email){
System.out.println(email.getInfo());
}
}
得到的结果为:
没有进行依赖倒转
使用接口的方式来进行依赖倒处理操作
使用接口的方式来对信息的接收处理
接口依赖倒转
使用接口来对信息进行接收处理
操作如下:
package com.yt.dependencyInversion.dependencyInversion;
import java.util.concurrent.Semaphore;
/**
* @program: designPattern
* @description
* @author: YangTao
* @create: 2024-02-20 22:24
**/
public class DependencyInversion {
public static void main(String[] args) {
Person person = new Person();
person.receive(new Weixin());
person.receive(new QQ());
}
}
interface Email{
void getMessage();
}
class Weixin implements Email{
@Override
public void getMessage() {
System.out.println("微信");
}
}
class QQ implements Email{
@Override
public void getMessage() {
System.out.println("QQ");
}
}
class Person{
public void receive(Email email){
email.getMessage();
}
}
含有三种方式来实现依赖倒转的原则:
使用接口的方式来实现依赖倒转
package com.yt.dependencyInversion.dependencyInversion;
/**
* @program: designPattern
* @description
* @author: YangTao
* @create: 2024-02-20 22:32
**/
public class InterfaceDependencyInversion {
public static void main(String[] args) {
OpenAndClose openAndClose = new OpenAndClose();
openAndClose.open(new Tv());
}
}
interface IOpenAndClose{
void open(IIv iIv);
}
interface IIv{
void play();
}
class OpenAndClose implements IOpenAndClose{
//专门是使用接口来进行信息的接收操作
@Override
public void open(IIv iIv) {
iIv.play();
}
}
class Tv implements IIv{
@Override
public void play() {
System.out.println("打开电视,看电视");
}
}
使用构造方法来进行依赖传递
package com.yt.dependencyInversion.dependencyInversion;
/**
* @program: designPattern
* @description
* @author: YangTao
* @create: 2024-02-20 22:49
**/
public class ConstructDependencyInversion {
public static void main(String[] args) {
OpenAndClose1 openAndClose1 = new OpenAndClose1(new ITv1Test());
openAndClose1.open();
}
}
interface IOpenAndClose1{
public void open();
}
interface ITv1{
public void play();
}
class ITv1Test implements ITv1{
@Override
public void play() {
System.out.println("在玩电视!");
}
}
class OpenAndClose1 implements IOpenAndClose1{
public ITv1 iTv1;
public OpenAndClose1(ITv1 iTv1) {
this.iTv1 = iTv1;
}
@Override
public void open() {
iTv1.play();
}
}
使用setter的方法来进行依赖传递
package com.yt.dependencyInversion.dependencyInversion;
/**
* @program: designPattern
* @description
* @author: YangTao
* @create: 2024-02-20 22:49
**/
public class ConstructDependencyInversion {
public static void main(String[] args) {
OpenAndClose1 openAndClose1 = new OpenAndClose1(new ITv1Test());
openAndClose1.open();
}
}
interface IOpenAndClose1{
public void open();
}
interface ITv1{
public void play();
}
class ITv1Test implements ITv1{
@Override
public void play() {
System.out.println("在玩电视!");
}
}
class OpenAndClose1 implements IOpenAndClose1{
public ITv1 iTv1;
public OpenAndClose1(ITv1 iTv1) {
this.iTv1 = iTv1;
}
@Override
public void open() {
iTv1.play();
}
}
依赖倒转的细节:
-
在底层模块尽量要都含有抽象类或者是接口,保持程序的稳定性!
-
变量的声明类型尽量要是抽象类或者是接口类型的,这样我们的变量引用和市级对象间,就会存在一个缓冲层保持程序的可拓展性。
-
继承要准守历史替代原则