🔖🔖看韩顺平讲设计模式原则-依赖倒转原则,代码实践。
依赖倒转原则(dependence invertion principle)
- 高层模块不应该依赖底层模块(类结继承类),二者都应该依赖其抽象(接口、抽象类)
- 抽象不应该依赖细节,细节应该依赖抽象
- 依赖倒转的中心思想是面向接口编程
- 设计理念:高层模块多是接口或抽象类
- 接口和抽象类的目的是制定规范,而不涉及具体的操作,把展现细节的任务交给他们的实现类去完成。
抛出问题
Person 接收消息的功能
1 | public class DependencyInversion { |
如果接受的消息是短信等类型的,则先要新增类似email的类,同时Person 类也要增加相应的接受方法。
解决思路
引入一个抽象的接口IReceiver,标识接收者,这样Person 类与接口发生依赖。
因为,email 和短信等等属于一个接收种类,他们各自实现IReceiver 接口就可以了,这样就符合依赖倒转原则(符合开始说的:细节应该依赖抽象)
1 | public class DependencyInversion { |
现在添加接收短信消息的方式,该怎么办?
添加一个接受者
接口,Person 类依赖接收者接口,使用的时候,接收哪种信息就创建哪种类去先实现接收者接口,再交给Person 类引用。
1 | public class DependencyInversion { |
依赖关系传递的三种方式和应用案例
写新功能的时候可以对照实现的是play()
方法
- 接口传递
1 | public class Example1 { |
- 构造方法传递
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40public class Example2 {
public static void main(String[] args) {
OpenAndClose openAndClose = new OpenAndClose(new XiaoMiTV());
openAndClose.open();
OpenAndClose openAndClose1 = new OpenAndClose(new SonyTv());
openAndClose1.open();
}
}
interface IOpenAndClose {
public void open();
}
interface ITv {
public void play();
}
class OpenAndClose implements IOpenAndClose {
private ITv tv;
public OpenAndClose(ITv tv) {
this.tv = tv;
}
public void open() {
this.tv.play();
}
}
//定义小米电视
class XiaoMiTV implements ITv {
public void play() {
System.out.println("播放小米电视");
}
}
// 定义索尼电视
class SonyTv implements ITv {
public void play() {
System.out.println("播放索尼电视");
}
} - setter 方式传递
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40public class Example3 {
public static void main(String[] args) {
OpenAndClose openAndClose = new OpenAndClose();
openAndClose.setTv(new XiaoMiTV());
openAndClose.open();
openAndClose.setTv(new SonyTv());
openAndClose.open();
}
}
interface IOpenAndClose {
public void open();
public void setTv(ITv tv);
}
interface ITv {
public void play();
}
class OpenAndClose implements IOpenAndClose {
private ITv tv;
public void setTv(ITv tv) {
this.tv = tv;
}
public void open() {
this.tv.play();
}
}
//定义小米电视
class XiaoMiTV implements ITv {
public void play() {
System.out.println("播放小米电视");
}
}
// 定义索尼电视
class SonyTv implements ITv {
public void play() {
System.out.println("播放索尼电视");
}
}注意事项和细节
- 底层模块尽量都要有抽象类或接口,或者两者都有
- 变量的声明类尽量是抽象类或接口,这样我们的变量引用和实例对象间就存在一个缓冲层,利于程序的扩展和优化。
- 继承时遵循里氏替换原则