设计原则--依赖倒转原则

依赖倒转原则:

  1. 高层模块不应该依赖底层模块。两个都应该依赖抽象
  2. 抽象不应该依赖细节。细节应该依赖抽象

字面意思:
1. 依赖:一个类需要依赖其他类
2. 倒转:不直接依赖于这个类,而是依赖其接口或抽象类

说白了,就是针对接口编程,不要针对实现编程

不遵循依赖倒转原则的例子:

public class demo {
    public static void main(String[] args) {
        Person person = new Person();
        person.receive(new Email());
    }
}
class Email{
    public String getInfo(){
        return "Email get info";
    }
}
class Person{
    public void receive(Email email){   //Person类直接依赖于Email类,没有依赖于抽象
        System.out.println(email.getInfo());
    }
}
如果有新的需求,需要接受微信的消息和短信的消息,如果是这种方式,则需要增加receive(WeiXin weixing)receive(DuanXing duanxing)方法,
而且可以发现,高层的逻辑(即Person对象接受消息的逻辑)是不变的,但是底层逻辑(即接受什么类型的消息)一旦增加,则需要对Person进行改变,耦合度较高

遵循依赖倒转:

public class demo {
    public static void main(String[] args) {
        Person person = new Person();
        person.receive(new Email());
        person.receive(new WeiXin());
    }
}
interface IReceiver{
    String getInfo();
}
class Email implements IReceiver{
    public String getInfo(){
        return "Email get info";
    }
}
class WeiXin implements IReceiver{
    public String getInfo(){
        return "WeiXin get info";
    }
}
class Person{
    public void receive(IReceiver receiver){   //依赖于抽象(接口)
        System.out.println(receiver.getInfo());
    }
}

《大话设计模式》:
面向过程的开发,为了使得常用可以复用,一般都会把常用代码写成许多函数的程序库,在做新的项目时去调用这些底层的函数就可以了。比如访问数据库,只要把访问数据库的代码写成函数,每次做新项目时去调用这些函数。这叫做:高层模块依赖底层模块
但是:
做新项目时,可能发现业务逻辑的高层模块是一样的,但客户希望使用不同数据库。我们希望使用这些高层模块,但是这些高层模块都是与底层的数据库绑定在一起,没办法复用这些高层模块。
如果是依赖于接口编程,哪怕更换数据库,只要实现不同数据库对接口的实现,高层模块依然可以服用且无需修改。

依赖传递的三种方式:
1. 通过接口传递

public class demo {
    public static void main(String[] args) {
        IAnimal iAnimal = new Person();
        iAnimal.eat(new Orange());
    }
}
interface IAnimal{
    void eat(IFood food);  //依赖于IFood接口
}
interface IFood{
    void taste();
}
class Orange implements IFood{
    @Override
    public void taste() {
        System.out.println("Orange taste ...");
    }
}
class Person implements IAnimal{
    @Override
    public void eat(IFood food) {  
        food.taste();
    }
}

2. 通过构造方法传递

public class demo {
    public static void main(String[] args) {
        IAnimal iAnimal = new Person(new Orange());
        iAnimal.eat();
    }
}
interface IAnimal{
    void eat();
}
interface IFood{
    void taste();
}
class Orange implements IFood{
    @Override
    public void taste() {
        System.out.println("Orange taste ...");
    }
}
class Person implements IAnimal{
    IFood food;
    public Person(IFood food){  //通过构造方法传递依赖关系
        this.food = food;
    }
    @Override
    public void eat() {
        this.food.taste();
    }
}

3. 通过setter传递

public class demo {
    public static void main(String[] args) {
        IAnimal iAnimal = new Person();
        iAnimal.setFood(new Orange());
        iAnimal.eat();
    }
}
interface IAnimal{
    void eat();
    void setFood(IFood food);  //通过set方法传入依赖关系
}
interface IFood{
    void taste();
}
class Orange implements IFood{
    @Override
    public void taste() {
        System.out.println("Orange taste ...");
    }
}
class Person implements IAnimal{
    IFood food;
    @Override
    public void setFood(IFood food){
        this.food = food;
    }
    @Override
    public void eat() {
        this.food.taste();
    }
}

依赖倒转原则注意事项:

  1. 低层模块尽量都要有抽象类或者接口
  2. 变量的声明类型尽量是抽象类或者接口,这样我们的变量引用和实际对象间就存在一层缓冲层(变量指向抽象类/接口,实际运行时会通过多态找到实际的类型),便于扩展
  3. 继承时遵循里式替换原则
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值