四 设计模式七大原则之依赖倒置原则
作者:互联网
1 基本介绍
依赖倒置原则是指 :
- 高层模块不应该依赖低层模块, 两者都应该依赖抽象
- 抽象不应该依赖细节,细节应该依赖抽象
- 依赖倒置的中心思想是面对接口编程
- 依赖倒置原则是基于这样的设计理念:
相对于细节的多变性,抽象的东西要稳定的多.抽象为基础的架构比以细节为基础的架构要稳定的多.在java中,抽象指的是接口或抽象类,细节就是具体的实现类. - 使用接口或者抽象类的目的就是定制好规范,而不涉及任何具体的操作,把展现细节的任务交给他们的实现类去实现
2 应用案例
package com.andy.principle.inversion;
public class DependecyInversion {
public static void main(String[] args) {
Person person = new Person();
person.receive(new Email());
}
}
class Email{
public String getInfo(){
return "电子邮件信息:hello,world";
}
}
class Person{
public void receive(Email email){
System.out.println(email.getInfo());
}
}
**分析 : **
上面的例子中 Person 类中的 receive 的参数是Email,然后调用 getInfo 方法模拟通信. 我们试想一下,如果Person 想新添加 其他的通信方式,比如微信,短信等,那么就要新增类,而且Person 类 也要增加相应的接收方法.这样子很不利于维护和添加新功能.所以说上面的设计思路是不合适的.那么我们下面用依赖倒置原则对上面的例子进行改进.
3 改进
package com.andy.principle.inversion.improve;
public class DependecyInversion {
public static void main(String[] args) {
Person person = new Person();
person.receive(new Email());
person.receive(new WeiXin());
}
}
interface IReceiver{
public String getInfo();
}
class Email implements IReceiver{
public String getInfo(){
return "电子邮件信息:hello,world";
}
}
class WeiXin implements IReceiver{
public String getInfo(){
return "微信信息:hello,ok";
}
}
class Person{
public void receive(IReceiver receiver){
System.out.println(receiver.getInfo());
}
}
**分析 : **
上面的改进方案中,我们引用一个抽象的接口 IReceiver,表示接受者,这样Person 类与接口IReceiver 发生依赖,现在新增一种通信方式就只需要实现 IReceiver 类就可以了.这样就符合依赖倒置原则.
一般依赖倒置原则应该注意事项:
- 底层模块尽量都要有抽象或者接口,或者两者都有,这样程序的稳定性会更好.
- 变量的声明类型尽量是抽象或者是接口,这样我们的变量引用和实际对象间就存在一个缓冲层,利于程序的拓展和优化.
- 继承时遵循里氏替换原则
4 依赖关系传递的三种关系
依赖关系传递方式一种有三种:
- 接口传递
- 构造方法传递
- setter方法传递
下面我们一一来说明一下:
4.1 接口传递
package com.andy.principle.inversion.improve;
public class DependencyPass {
public static void main(String[] args) {
ChangHong changHong = new ChangHong();
IOpenAndClose openAndClose = new OpenAndClose();
openAndClose.open(changHong);
}
}
//开关接口
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();
}
}
**分析 : **
这里定义了两个接口 IOpenAndClose 和 ITV,并分别在类OpenAndClose 和类ChangHong中实现了这两个接口.看 IOpenAndClose 接口中的open函数,形参是ITV接口,调用是只要把实现了ITV接口的传进去就能依赖ITV接口了.这样方法有点绕,现在这个程序有点简单,看不出来这种方法的好处,但很多架构都是采用这样方法.
4.2 构造方法传递
interface IOpenClose {
public void open();//抽象方法
}
interface ITV {
public void play();//抽象方法
}
class OpenAndClose implements IOpenClose{
public ITV tv;
public OpenAndClose(ITV tv){ //构造器
this.tv = tv;
}
@Override
public void open() {
this.tv.play();
}
}
**分析 : **
像上面定义两个接口 IOpenClose 和 ITV ,而OpenAndClose 类 实现 IOpenClose ,而且OpenAndClose 类 中定义了一个 ITV属性,在OpenAndClose 类中给该属性赋值,而实现的open函数中调用ITV 的 paly方法,这也是一种方法.这也是符合依赖倒置原则的.
4.3 setter方法传递
interface IOpenAndClose{
public void open();
public void setTv(ITV tv);
}
interface ITV {
public void play();//抽象方法
}
class OpenAndClose implements IOpenAndClose{
private ITV tv;
@Override
public void open() {
this.tv.play();
}
@Override
public void setTv(ITV tv) {
this.tv = tv;
}
}
class ChangHong implements ITV{
@Override
public void play() {
System.out.println("长虹电视,打开");
}
}
**分析 : **
setter方法传递 和 构造方法传递基本是一样的,唯一的区别在与给ITV属性的赋值一个是在构造器中,一个赋值在setter方法中.
andyonlines 发布了19 篇原创文章 · 获赞 1 · 访问量 228 私信 关注标签:原则,tv,void,接口,class,ITV,倒置,设计模式,public 来源: https://blog.csdn.net/andyonlines/article/details/104084942