依赖倒转原则
依赖倒转原则
基本介绍
依赖倒转原则(Dependence Inversion Principle):
- 1.高层模块,不要依赖底层模块,二者都应该依赖其抽象。
- 2.抽象不应该依赖细节,细节应该依赖抽象。
- 3.依赖倒转的核心思想是面向接口编程。
- 4.依赖倒转原则基于这样的设计理念:相对于细节的多变,抽象的东西就稳定的多。以抽象为基础搭建的架构,比细节为基础的架构要稳定的多。在Java中,抽象是指定义好的接口或抽象类,细节是其具体的实现类。
- 5.使用接口或抽象类的目的就是指定好规范,不涉及具体的操作,把具体细节的任务交给具体的实现类实现。
案例1
/**
* @author 长名06
* @version 1.0
* 案例1 分析
* Person类直接依赖Email类,违反了依赖倒转原则
* 如果Person类对象还要查看其他的信息,就需要额外新增加方法
* 改进,应该抽象一个信息接口,具体的信息类实现这个接口
*/
public class Inversion1 {
public static void main(String[] args) {
new Person().showInfo(new Email());
}
}
class Email{
public String getInfo(){
return "邮箱消息: hello world!";
}
}
class Person{
public void showInfo(Email email){
System.out.println(email.getInfo());
}
}
案例2
/**
* @author 长名06
* @version 1.0
* 使用依赖倒转原则改进
*/
public class Inversion2 {
public static void main(String[] args) {
new Person().showInfo(new Email());
new Person().showInfo(new WerXin());
}
}
interface Information{
public String getInfo();
}
class Email implements Information{
@Override
public String getInfo() {
return "邮箱消息: hello world!";
}
}
class WerXin implements Information{
@Override
public String getInfo() {
return "微信消息: hello world!";
}
}
class Person{
public void showInfo(Information information){
System.out.println(information.getInfo());
}
}
依赖关系的实现方式
分别是接口传递,构造方法传递,setter方式传递。
/**
* 模拟依赖传递的三种方式
* @author 小少年
* @version 1.0
*/
public class DependencePass {
public static void main(String[] args) {
OpenAndClose openAndClose = new OpenAndClose();
openAndClose.open(new ChangHong());
ChangHong1 changHong1 = new ChangHong1();
OpenAndClose1 openAndClose1 = new OpenAndClose1(changHong1);
openAndClose1.open();
ChangHong2 changHong2 = new ChangHong2();
OpenAndClose2 openAndClose2 = new OpenAndClose2();
openAndClose2.setItv(changHong2);
openAndClose2.open();
}
}
//依赖 就是在本类中使用到另一个类的这种关系
//方式1 通过接口实现依赖传递
interface IOpenAndClose{//用于开关电视的接口
public void open(ITV tv);//使用一个接口的对象作为方法的参数
}
interface ITV{//电视的接口
public void play();
}
class ChangHong implements ITV{//具体的一个电视品牌
@Override
public void play() {
System.out.println("长虹电视,打开");
}
}
class OpenAndClose implements IOpenAndClose{//具体的一个开关接口
@Override
public void open(ITV tv) {
tv.play();
}
}
//方式2 通过构造方法实现依赖传递
interface IOpenAndClose1{
public void open();
}
interface ITV1{
public void play();
}
class ChangHong1 implements ITV1{
@Override
public void play() {
System.out.println("长虹电视1,打开");
}
}
class OpenAndClose1 implements IOpenAndClose1{
public ITV1 itv;
public OpenAndClose1(ITV1 itv){
this.itv = itv;
}
@Override
public void open() {
itv.play();
}
}
//方式3 通过setter方法实现依赖传递
interface IOpenAndClose2{
public void open();
}
interface ITV2{
public void play();
}
class ChangHong2 implements ITV2{
@Override
public void play() {
System.out.println("长虹电视2 打开");
}
}
class OpenAndClose2 implements IOpenAndClose2{
public ITV2 itv;
public void setItv(ITV2 itv){
this.itv = itv;
}
@Override
public void open() {
this.itv.play();
}
}
注意事项和细节
- 1.底层模块尽量都要由抽象类或接口,或者两者都有,程序稳定性更好。
- 2.对象的声明类型尽量都是抽象类或接口,这样在我们的对象引用和实际对象间,就存在一个缓冲层,利于程序扩展和优化。
- 3.继承时,要遵守里氏替换原则(下次就写)。
只是为了记录自己的学习历程,且本人水平有限,不对之处,请指正。