依赖倒置原则(Dependence Inversion Principle,DIP)的原始定义为:高层模块不应该依赖低层模块,两者都应该依赖其抽象;

抽象不应该依赖细节,细节应该依赖抽象。

其核心思想是:要面向接口编程,不要面向实现编程。

依赖倒置原则的目的是通过要面向接口的编程来降低类间的耦合性,所以我们在实际编程中只要遵循以下4点,就能在项目中满足这个规则。

1.每个类尽量提供接口或抽象类,或者两者都具备。

2.变量的声明类型尽量是接口或者是抽象类。

3.任何类都不应该从具体类派生。

4.使用继承时尽量遵循里氏替换原则

下面给出一个具体的例子进行说明。

UML类图:

 

有三种方式可以实现依赖倒置:

方式1:使用接口传递,QQPlayer实现了IPlayerA,而IPlayerA依赖于IFile,这样通过IPlayerA将IFile传递给了QQPlayer类的对象。

方式2:使用构造函数,NEPlayer实现了IPlayerB,并且NEPlayer关联IFile (实线箭头),通过构造函数将IFile的实例传递给NEPlayer类的对象。

方式3:使用属性Setter方法,KWPlayer实现了IPlayerB,并且KWPlayer关联IFile (实现箭头),通过私有变量的Setter方法setFile(),将IFile实例传递给KWPlayer类的对象。

下面是根据UML类图实现的Java代码:

 1 public interface IFile {
 2     public String getFileName();
 3 }
 4 
 5 public class MusicFile implements IFile {
 6 
 7     private String fileName;
 8 
 9     public MusicFile(String fileName) {
10         this.fileName = fileName;
11     }
12 
13     @Override
14     public String getFileName() {
15         return this.fileName;
16     }
17 
18 }
19 
20 public interface IPlayerA {
21     public void playFile(IFile file);
22 }
23 
24 public interface IPlayerB {
25     public void play();
26 }
27 
28 public class QQPlayer implements IPlayerA {
29     @Override
30     public void playFile(IFile file) {
31         String fileName = file.getFileName();
32         System.out.println("QQ音乐开始播放歌曲:" + fileName);
33     }
34 }
35 
36 public class NEPlayer implements IPlayerB {
37     private IFile file;
38 
39     public NEPlayer(IFile file) {
40         this.file = file;
41     }
42 
43     @Override
44     public void play() {
45         String fileName = this.file.getFileName();
46         System.out.println("网易音乐开始播放歌曲:" + fileName);
47     }
48 }
49 
50 public class KWPlayer implements IPlayerB {
51 
52     private IFile file;
53 
54     public void setFile(IFile file) {
55         this.file = file;
56     }
57 
58     @Override
59     public void play() {
60         // TODO Auto-generated method stub
61         String fileName = this.file.getFileName();
62         System.out.println("酷我音乐开始播放歌曲:" + fileName);
63     }
64 }
65 
66 public class Client {
67     public static void main(String[] args) {
68         byInterface();
69         byConstruct();
70         bySetter();
71     }
72 
73     // 方式1:接口方式
74     public static void byInterface() {
75         IFile file = new MusicFile("盗将行");
76         QQPlayer player = new QQPlayer();
77         player.playFile(file);
78     }
79 
80     // 方式2:构造函数方式
81     public static void byConstruct() {
82         IFile file = new MusicFile("出山");
83         NEPlayer player = new NEPlayer(file);
84         player.play();
85     }
86 
87     // 方式3:属性Setter方式
88     public static void bySetter() {
89         IFile file = new MusicFile("芒种");
90         KWPlayer player = new KWPlayer();
91         player.setFile(file);
92         player.play();
93     }
94 }

 

posted on 2019-10-29 14:22  Sempron2800+  阅读(253)  评论(0编辑  收藏  举报