设计原则——接口隔离原则

分解接口:ISP原则在学生成绩管理中的应用

1.全称

  • Interface Segregation Principle
  • 缩写为:ISP

2.解释

  • 要求程序员尽量将臃肿庞大的接口拆分成更小的和更具体的接口,让接口中只包含客户感兴趣的方法
    • 单一职责原则注重的是职责,而接口隔离原则注重的是对接口依赖的隔离
    • 单一职责原则主要是约束类,它针对的是程序中的实现和细节;接口隔离原则主要约束接口,主要针对抽象和程序整体框架的构建。

3.接口隔离原则的实现方法

1.场景
  • 学生成绩管理程序一般包含插入成绩、删除成绩、修改成绩、计算总分、计算均分、打印成绩信息、査询成绩信息等功能
  • 如果将这些功能全部放到一个接口中显然不太合理
  • 比较合理的做法是将它们分别放在输入模块、统计模块和打印模块等 3 个模块中
    • 输入模块

      插入成绩
      删除成绩
      修改成绩

    • 统计模块

      计算均分
      计算均分

    • 打印模块

      打印成绩信息
      査询成绩信息

2.实现
class Student:
    def __init__(self, name, subject, score):
        self._name = name
        self._subject = subject
        self._score = score

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, value):
        self._name = value

    @property
    def subject(self):
        return self._subject

    @subject.setter
    def subject(self, value):
        self._subject = value

    @property
    def score(self):
        return self._score

    @score.setter
    def score(self, value):
        self._score = value


class StudentScoreManager:
    student_list = []

    def insert_score(self, student: Student):
        raise NotImplementedError

    def delete_score(self, student: Student):
        raise NotImplementedError

    def update_score(self, student: Student):
        raise NotImplementedError

    def calculate_average_score(self, student: Student):
        raise NotImplementedError

    def calculate_total_score(self, student: Student):
        raise NotImplementedError

    def print_score(self, student: Student):
        raise NotImplementedError

    def query_score(self, student: Student):
        raise NotImplementedError


class InputManager(StudentScoreManager):
    def insert_score(self, student):
        self.student_list.append(student)

    def delete_score(self, student):
        self.student_list.remove(student)

    def update_score(self, student):
        for stu in self.student_list:
            if student.name == stu.name and student.subject == stu.subject:
                stu.score = student.score
                break


class StatisticsManager(StudentScoreManager):
    def calculate_average_score(self, student):
        sum_score = 0
        count = 0
        for stu in self.student_list:
            if student.name == stu.name:
                count += 1
                sum_score += stu.score
        return sum_score / count

    def calculate_total_score(self, student):
        sum_score = 0
        for stu in self.student_list:
            if student.name == stu.name:
                sum_score += stu.score
        return sum_score


class OutputManager(StudentScoreManager):
    def print_score(self, student):
        for stu in self.student_list:
            if student.name == stu.name:
                yield f"姓名:{stu.name}, 科目:{stu.subject}, 成绩:{stu.score}"

    def query_score(self, student):
        for stu in self.student_list:
            if student.score == stu.score:
                yield f"姓名:{stu.name}, 科目:{stu.subject}, 成绩:{stu.score}"


if __name__ == '__main__':
    s1 = Student("张三", "数学", 87)
    s2 = Student("张三", "语文", 76)
    s3 = Student("李四", "英语", 87)
    s4 = Student("李四", "英语", 87)

    im = InputManager()
    im.insert_score(s1)
    im.insert_score(s2)
    im.insert_score(s3)
    im.insert_score(s4)

    # InputManager类没有输出学生的功能(报错)
    # im.print_score()
    print('----------------输出张三的成绩----------------')
    om = OutputManager()
    result = om.print_score(s1)
    for score_info in result:
        print(score_info)

    print('----------------修改张三的语文成绩----------------')
    s5 = Student("张三", "语文", 89)
    im.update_score(s5)
    result = om.print_score(s1)
    for score_info in result:
        print(score_info)

    print('----------------查询成绩为87的学生信息----------------')
    for resp in om.query_score(s1):
        print(resp)

    print('----------------输出张三的总成绩----------------')
    sm = StatisticsManager()
    print(sm.calculate_total_score(s1))

    print('----------------输出李四的平均成绩----------------')
    sm = StatisticsManager()
    print(sm.calculate_average_score(s3))
----------------输出张三的成绩----------------
姓名:张三, 科目:数学, 成绩:87
姓名:张三, 科目:语文, 成绩:76
----------------修改张三的语文成绩----------------
姓名:张三, 科目:数学, 成绩:87
姓名:张三, 科目:语文, 成绩:89
----------------查询成绩为87的学生信息----------------
姓名:张三, 科目:数学, 成绩:87
姓名:李四, 科目:英语, 成绩:87
姓名:李四, 科目:英语, 成绩:87
----------------输出张三的总成绩----------------
176
----------------输出李四的平均成绩----------------
87.0

4.接口隔离原则的优点

1.将臃肿庞大的接口分解为多个粒度小的接口,可以预防外来变更的扩散,提高系统的灵活性和可维护性。

2.接口隔离提高了系统的内聚性,减少了对外交互,降低了系统的耦合性。

3.如果接口的粒度大小定义合理,能够保证系统的稳定性;但是,如果定义过小,则会造成接口数量过多,使设计复杂化;如果定义太大,灵活性降低,无法提供定制服务,给整体项目带来无法预料的风险。

4.使用多个专门的接口还能够体现对象的层次,因为可以通过接口的继承,实现对总接口的定义。

5.能减少项目工程中的代码冗余。过大的大接口里面通常放置许多不用的方法,当实现这个接口的时候,被迫设计冗余的代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值