开发原则五:接口隔离ISP

在这里插入图片描述

在软件工程领域,接口隔离原则(ISP)规定不应强迫客户端依赖它不使用的方法。ISP将非常大的接口拆分为更小和更具体的接口,以便客户端只需知道它们感兴趣的方法。这种缩小的接口也称为角色接口。ISP旨在使系统分离,从而更容易重构,更改和重新部署。ISP是面向对象设计的五个SOLID原则之一,类似于GRASP的高内聚原则。

接口隔离核心思想

客户端不应该被迫依赖它不使用的接口

接口隔离的核心要求

将大的接口拆分为多个小的接口,每个接口只包含客户端所需的方法。这样可以避免客户端被迫实现一些它们不需要的方法。
类与类之间的依赖通过接口进行,而不是通过具体的实现类。这样可以降低类之间的耦合度。
接口设计应该精简、高内聚,每个接口只负责一个特定的行为或功能。

接口隔离与单一原则

从功能上来看,接口隔离原则和单一职责原则都是为了提高类的内聚, 降低类之间的耦合, 体现了封装的思想。但二者还是有区别的。
(1)从原则约束来看: 接口隔离原则更关注的是接口依赖程度的隔离;而单一职责原则更加注重的是接口职责的划分。
(2)从接口的细化程度来看: 单一职责原则对接口的划分更加精细,而接口隔离原则注重的是相同功能的接口的隔离。接口隔离里面的最小接口有时可以是多个单一职责的公共接口。
(3)单一职责原则更加偏向对业务的约束: 接口隔离原则更加偏向设计架构的约束。这个应该好理解,职责是根据业务功能来划分的,所以单一原则更加偏向业务;而接口隔离更多是为了“高内聚”,偏向架构的设计。

接口隔离的优点

接口隔离原则是为了约束接口、降低类对接口的依赖性,遵循接口隔离原则有以下 5 个优点。
将臃肿庞大的接口分解为多个粒度小的接口,可以预防外来变更的扩散,提高系统的灵活性和可维护性。
接口隔离提高了系统的内聚性,减少了对外交互,降低了系统的耦合性。
如果接口的粒度大小定义合理,能够保证系统的稳定性;然而,如果定义过小,则会造成接口数量过多,使设计复杂化;如果定义太大,灵活性降低,无法提供定制服务,给整体项目带来无法预料的风险。
使用多个专门的接口能够体现对象的层次,因为可以通过接口的继承,实现对总接口的定义。
能减少项目工程中的代码冗余。过大的大接口里面通常放置许多不用的方法,当实现这个接口的时候,被迫设计冗余的代码。

案例实践

学生成绩管理程序一般包含查询成绩、新增成绩、删除成绩、修改成绩、计算总分、计算平均分、打印成绩信息等功能,通常我们会怎么做呢

public interface IStudentScore {
    // 查询成绩
    public void queryScore();
    // 修改成绩
    public void updateScore();
    // 添加成绩
    public void saveScore();
    // 删除成绩
    public void delete();
    // 计算总分
    public double sum();
    // 计算平均分
    public double avg();
    // 打印成绩单
    public void printScore();
}

我们会吧所有的功能都放在一个接口里面. 这会产生什么样的问题呢?
首先, 接口的方法很多, 不利于扩展. 比如: 学生只有查看成绩,打印成绩单的权限, 没有增删改的权限; 老师拥有所有的权限.
查询成绩单:

public class QueryScore implements IStudentScore{
    @Override
    public void queryScore() {
        // 查询成绩
    }
    @Override
    public void updateScore() {
         // 没有权限
    }
    @Override
    public void saveScore() {
        // 没有权限
    }
    @Override
    public void delete() {
        // 没有权限
    }
    @Override
    public double sum() {
        // 没有权限
        return 0;
    }
    @Override
    public double avg() {
        // 没有权限
        return 0;
    }
    @Override
    public void printScore() {
        //打印成绩单
    }
}

操作成绩单

public class Operate implements IStudentScore{
    @Override
    public void queryScore() {
        
    }
    @Override
    public void updateScore() {
    }
    @Override
    public void saveScore() {
    }
    @Override
    public void delete() {
    }
    @Override
    public double sum() {
        return 0;
    }
    @Override
    public double avg() {
        return 0;
    }
    @Override
    public void printScore() {
    }
}

可以看出问题. 查询成绩单, 我们只会用到两个方法, 可是因为实现了接口, 不得不重写所有的方法.如果这时候增加需求–发送给家长, 只有老师才有这个权限, 学生没有这个权限. 可是, 在接口中增加一个抽象方法以后, 所有的实现类都要重写这个方法. 这就违背了开闭原则.
采用接口隔离原则设计的接口

public interface IQueryScore {
    // 查询成绩
    public void queryScore();
    // 打印成绩单
    public void printScore();
}
public interface IOperateScore {
    // 修改成绩
    public void updateScore();
    // 添加成绩
    public void saveScore();
    // 删除成绩
    public void delete();
    // 计算总分
    public double sum();
    // 计算平均分
    public double avg();
}
public class StudentOperate implements IQueryScore{
    @Override
    public void queryScore() {
        // 查询成绩
    }
    @Override
    public void printScore() {
        //打印成绩单
    }
}
public class TeacherOperate implements IQueryScore, IOperateScore{
    @Override
    public void queryScore() {
    }
    @Override
    public void updateScore() {
    }
    @Override
    public void saveScore() {
    }
    @Override
    public void delete() {
    }
    @Override
    public double sum() {
        return 0;
    }
    @Override
    public double avg() {
        return 0;
    }
    @Override
    public void printScore() {
    }
}

我们将原来的一个接口进行了接口拆分. 分为查询接口和操作接口. 这样学生端就不需要重写和他不相关的接口了.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值