从零开始学习Java设计模式 | 软件设计原则篇:接口隔离原则

Posted 李阿昀

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从零开始学习Java设计模式 | 软件设计原则篇:接口隔离原则相关的知识,希望对你有一定的参考价值。

在本讲,我将为大家介绍软件设计原则里面的第四个原则,即接口隔离原则。

概述

接口隔离原则是指客户端不应该被迫依赖于它不使用的方法,一个类对另一个类的依赖应该建立在最小的接口上面。

这句话可能不是很好理解,所以下面我会画一张图来解释一下。先看的是前半段话,客户端不应该被迫依赖于它不使用的方法,这是什么意思呢?

从上图中,相信大家能够更好地理解前半段话的内容,所以,在上述这种情景下,我们是不能使用继承关系的。那么,现在我们应该如何对其进行改进呢?其实,在接口隔离原则概述的后半段话中就已经说了,即一个类对另一个类的依赖应该建立在最小的接口上面。改进之后,就变成下图所示的这样了。

通过上面两张图的解释,相信大家对于接口隔离原则的概念有了一个更深入的认识。

接下来,我们就通过一个例子来更深入的去理解一下接口隔离原则。

案例

这个例子就是安全门案例。

案例分析

我们现在需要创建一个美美侠品牌的安全门,该安全门具有防火、防水、防盗的功能。

要想做到这一点的话,咱们首先得设计出类图来。那我们应该如何去设计呢?可以将防火、防水、防盗等功能提取到一个接口里面,形成一套规范,所以,设计出来的类图应该如下所示。

如果你想要去设计安全门的话,那么你只需要去实现SafetyDoor接口,并重写它里面的所有的抽象方法就可以了。

接下来,我们便来通过代码实现以上安全门案例。

案例实现

打开咱们的maven工程,然后在com.meimeixia.principles包下创建一个子包,即demo4,接着在com.meimeixia.principles.demo4包下再创建一个子包,即before,我们首次是在该包下来存放咱们编写的代码的。接下来,我们就要正式开始编写代码来实现以上案例了。

首先,定义一个SafetyDoor接口,即安全门接口。

package com.meimeixia.principles.demo4.before;

/**
 * 安全门接口
 * @author liayun
 * @create 2021-05-27 21:13
 */
public interface SafetyDoor 

    // 防盗
    void antiTheft();

    // 防火
    void fireProof();

    // 防水
    void waterProof();


然后,定义以上接口的一个实现类,例如美美侠安全门。

package com.meimeixia.principles.demo4.before;

/**
 * 美美侠品牌的安全门类
 * @author liayun
 * @create 2021-05-27 21:18
 */
public class MeimeixiaSafetyDoor implements SafetyDoor 
    @Override
    public void antiTheft() 
        System.out.println("防盗");
    

    @Override
    public void fireProof() 
        System.out.println("防火");
    

    @Override
    public void waterProof() 
        System.out.println("防水");
    

最后,我们来编写一个测试类用作测试,不妨取名为Client。

package com.meimeixia.principles.demo4.before;

/**
 * @author liayun
 * @create 2021-05-27 21:23
 */
public class Client 

    public static void main(String[] args) 
        MeimeixiaSafetyDoor door = new MeimeixiaSafetyDoor();
        door.antiTheft();
        door.fireProof();
        door.waterProof();
    


以上测试类编写好之后,不妨来运行一下,如下图所示,可以看到,咱们设计的美美侠安全门确实具有了防盗、防火、防水的功能。

对于以上设计,你觉得存不存在什么问题啊?如果我们现在再提一个需求,即还想再创建一个阿昀品牌的安全门,而该安全门只具有防盗、防火功能,不具有防水功能,那么难道我们需要再去定义一个类,让它去实现SafetyDoor接口吗?很显然不能,因为如果让新建的类再去实现SafetyDoor接口的话,那么就意味着该类要被迫依赖于它不使用的方法,即防水的方法,这也就违背了接口隔离原则。

那么我们又该如何进行修改呢?下面就会说到。

案例改进

虽然我们实现了以上安全门案例,但是我们也看到该案例所存在的问题,即违背了接口隔离原则。因此,我们就得需要对其进行改进了。那如何进行改进呢?

首先,咱们得按照接口隔离原则来重新设计出以下类图。

从以上类图中可以看到,我们是将安全门的接口给它拆分成了不同的接口,分别是防盗接口、防火接口、防水接口。现在,如果我们想要去创建一个美美侠品牌的安全门的话,那么只需要让其分别去实现这三个接口就可以了。要是后期我们还想要再创建一个阿昀品牌的安全门的话,而该安全门只具有防盗、防火功能,那么我们只须让其去实现防盗、防火这两个接口就可以了。

分析完了之后,下面我们来看一下代码的具体实现。

首先,在com.meimeixia.principles.demo4包下再创建一个子包,即after,该包下存放的就是改进后的案例的代码。

然后,创建防盗接口。

package com.meimeixia.principles.demo4.after;

/**
 * 防盗接口
 * @author liayun
 * @create 2021-05-28 11:42
 */
public interface AntiTheft 

    void antiTheft();


接着,创建防火接口。

package com.meimeixia.principles.demo4.after;

/**
 * 防火接口
 * @author liayun
 * @create 2021-05-28 11:44
 */
public interface Fireproof 

    void fireproof();


紧接着,创建防水接口。

package com.meimeixia.principles.demo4.after;

/**
 * 防水接口
 * @author liayun
 * @create 2021-05-28 11:47
 */
public interface Waterproof 

    void waterproof();


以上三个接口定义完毕之后,接下来,我们来定义美美侠品牌的安全门类,并让其去实现以上三个接口。

package com.meimeixia.principles.demo4.after;

/**
 * @author liayun
 * @create 2021-05-28 11:50
 */
public class MeiMeiXiaSafetyDoor implements AntiTheft, Fireproof, Waterproof 
    @Override
    public void antiTheft() 
        System.out.println("防盗");
    

    @Override
    public void fireproof() 
        System.out.println("防火");
    

    @Override
    public void waterproof() 
        System.out.println("防水");
    

最后,来编写一个测试类进行测试。

package com.meimeixia.principles.demo4.after;

/**
 * @author liayun
 * @create 2021-05-28 11:56
 */
public class Client 

    public static void main(String[] args) 
        // 创建美美侠安全门对象
        MeiMeiXiaSafetyDoor door = new MeiMeiXiaSafetyDoor();
        // 调用功能
        door.antiTheft();
        door.fireproof();
        door.waterproof();
    


以上测试类编写好之后,不妨来运行一下,如下图所示,可以看到,咱们设计的美美侠安全门确实具有了防盗、防火、防水的功能。

这时,应该是解决了之前案例所存在的问题,为了验证这一点,我们在这儿再去定义一个阿昀品牌的安全门类,而且该类只具有防盗和防火功能,因此我们得让该类去实现防盗、防火这两个接口。

package com.meimeixia.principles.demo4.after;

/**
 * 阿昀安全门
 * @author liayun
 * @create 2021-05-28 12:01
 */
public class AyunSafetyDoor implements AntiTheft, Fireproof 
    @Override
    public void antiTheft() 
        System.out.println("防盗");
    

    @Override
    public void fireproof() 
        System.out.println("防火");
    

以上类定义完毕之后,我们再在Client测试类中编写如下代码进行测试。

package com.meimeixia.principles.demo4.after;

/**
 * @author liayun
 * @create 2021-05-28 11:56
 */
public class Client 

    public static void main(String[] args) 
        // 创建美美侠安全门对象
        MeiMeiXiaSafetyDoor door = new MeiMeiXiaSafetyDoor();
        // 调用功能
        door.antiTheft();
        door.fireproof();
        door.waterproof();

        System.out.println("===================");
        // 创建阿昀安全门对象
        AyunSafetyDoor door1 = new AyunSafetyDoor();
        // 调用功能
        door1.antiTheft();
        door1.fireproof();
    


这时,不妨来运行一下以上测试类,如下图所示,可以看到,咱们设计的阿昀安全门确实是只具有防盗、防火这俩功能。

至此,安全门案例我们就改进完毕了,现在更好地符合了接口隔离原则。

以上是关于从零开始学习Java设计模式 | 软件设计原则篇:接口隔离原则的主要内容,如果未能解决你的问题,请参考以下文章

从零开始学习Java设计模式 | 软件设计原则篇:里氏代换原则

从零开始学习Java设计模式 | 软件设计原则篇:里氏代换原则

从零开始学习Java设计模式 | 软件设计原则篇:合成复用原则

从零开始学习Java设计模式 | 软件设计原则篇:合成复用原则

从零开始学习Java设计模式 | 软件设计原则篇:依赖倒转原则

从零开始学习Java设计模式 | 软件设计原则篇:依赖倒转原则