设计模式六大原则(4):依赖倒置原则

定义:高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。

场景:类A直接依赖类B,假如要将类A改为依赖类C,则必须通过修改类A的代码来达成。这种场景下,类A一般是高层模块,负责复杂的业务逻辑;类B和类C是低层模块,负责基本的原子操作;假如修改类A,会给程序带来不必要的风险。

解决方案:遵循依赖倒置原则,将类A修改为依赖接口I,类B和类C各自实现接口I,类A通过接口I间接与类B或者类C发生联系,则会大大降低修改类A的几率。

上面用到很多泛泛的词语,为了帮助理解,对其进行大白话化:抽象就是指接口或抽象类,两者都是不能直接被实例化的;细节就是实现类,实现接口或继承抽象类而产生的类就是细节,其特点就是,可以直接被实例化。高层模块就是调用端,低层模块就是具体实现类。依赖倒置原则在 Java 语言中的表现就是:模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生的。这又是一个将理论抽象化的实例,其实一句话就可以概括:面向接口编程,或者说是面向抽象编程,这里的抽象指的是接口或者抽象类。

根据上面的场景,用代码更直观的来理解依赖倒置原则。现在有这样一个需求,一群孩子玩球类游戏,只要给他们一个球,便可开心的玩耍。代码如下:

篮球类:

/**
 * Created by LJW on 2018/8/24.
 * 篮球类
 */
public class Basketball {

    public String playBall(){
        return "一群孩子正在开心的打篮球......";
    }
}

孩子类:

/**
 * Created by LJW on 2018/8/24.
 * 孩子类
 */
public class Children{

    public void play(Basketball basketball){ //通过参数依赖了篮球类
        System.out.println(basketball.playBall());
    }
}

开始游戏:

Children children = new Children();
children.play(new Basketball());

输出结果:一群孩子正在开心的打篮球......

孩子玩的很开心,假如有一天,小朋友说,你天天让我们玩篮球,够够的,能不能换成踢足球?现在需求变了,好,我们新建一个足球类:

**
 * Created by LJW on 2018/8/24.
 * 足球类
 */
public class Football{

    public String playBall() {
        return "一群孩子正在开心的踢足球......";
    }
}

这时我们发现,这群孩子踢不了足球了!因为他们依赖了篮球类,孩子类和篮球类之间的耦合性太高了。要想让他们可以踢足球,必须来修改孩子类的代码,这不严重违背了开闭原则了吗?

如果类与类直接依赖于细节(如上面的孩子类和篮球类),那么他们之间就有了直接的耦合,当具体实现需要变化时,意味着要同时修改依赖者的代码,这限制了程序的可扩展性。下面我们遵循依赖倒置原则来重构上面的代码:

首先,我们引入一个球类的接口,只要属于球类运动,都实现该接口:

/**
 * Created by LJW on 2018/8/24.
 * 球类接口
 */
public interface IPlayBall {
    String playBall();
}

修改篮球类和足球类,让其实现IPlayBall接口:

/**
 * Created by LJW on 2018/8/24.
 * 篮球类
 */
public class Basketball implements IPlayBall {

    @Override
    public String playBall() {
        return "一群孩子正在开心的打篮球......";
    }
}
/**
 * Created by LJW on 2018/8/24.
 * 足球类
 */
public class Football implements IPlayBall{

    @Override
    public String playBall() {
        return "一群孩子正在开心的踢足球......";
    }
}

最后修改孩子类,不再让其依赖任何具体的球类,而是依赖球类接口,这样就遵循了依赖倒置原则:

/**
 * Created by LJW on 2018/8/24.
 * 孩子类
 */
public class Children{

    public void play(IPlayBall playBall){
        System.out.println(playBall.playBall());
    }
}

孩子的游戏开始啦:

Children children = new Children();
children.play(new Basketball());
children.play(new Football());

输出结果:

一群孩子正在开心的打篮球......

一群孩子正在开心的踢足球......

这时孩子们竖起来崇拜的大拇指~~这才是我们想要的!

这样修改后,可以随意的来扩展各种球类运动,而不再修改孩子类了。通过遵循依赖倒置原则,降低了类之间的耦合性,提高了系统的稳定性,减少了修改程序造成的风险。通过上面的例子我们可以发现,依赖倒置原则的核心是:抽象。理解了抽象,也就掌握了依赖倒置原则。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值