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