1.全称
- Composite Reuse Principle
- 缩写为:
CRP
2.解释
- 尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现
- 如果要使用继承关系,则必须严格遵循里氏替换原则。合成复用原则同里氏替换原则相辅相成的,两者都是开闭原则的具体实现规范
3.接口隔离原则的实现方法
1.场景:学校需要招聘一名老师,只负责讲课
- 1.现在有两个符合的角色:教授、教师
- 2.他们不仅都会教书,同时还都有其他能力
- 3.如果使用继承,只能使用其中一个的教书方法,同时他们的其他能力也被强制继承过来
- 4.如果使用组合的方式,就可以动态的引用对象,可以根据具体情况选择哪个对象的教书方式
class Person:
def __init__(self, name):
self.name = name
def talk(self):
pass
class Professor(Person):
def research(self):
"""研究"""
pass
def teaching(self):
"""教学"""
print(f"{self.name}正在讲高等数学")
class Teacher(Person):
def teaching(self):
"""教学"""
print(f"{self.name}正在讲小学算数")
def show(self):
"""表演"""
pass
class School:
def __init__(self, teacher):
# 复用的灵活性高。这种复用可以在运行时动态进行,新对象可以动态地引用与成分对象类型相同的对象
self.teacher = teacher
def attend_class(self):
self.teacher.teaching()
if __name__ == '__main__':
# 如果使用继承,就只能让教授或者老师其中一个来教书
# 如果学校只需要教书着一个功能,则继承对象的其他功能也被强制性的继承
t = Teacher("李毅")
s = School(t)
s.attend_class()
# 使用组合的方式,可以随时更换上课对象,同时也不会继承教师对象的其他方法和属性
t1 = Professor("杨勇")
s = School(t1)
s.attend_class()
李毅正在讲小学算数
杨勇正在讲高等数学
4.合成复用原则的重要性
1.继承的缺陷
-
继承复用破坏了类的封装性。因为继承会将父类的实现细节暴露给子类,父类对子类是透明的,所以这种复用又称为“白箱”复用。
-
子类与父类的耦合度高。父类的实现的任何改变都会导致子类的实现发生变化,这不利于类的扩展与维护。
-
它限制了复用的灵活性。从父类继承而来的实现是静态的,在编译时已经定义,所以在运行时不可能发生变化。
2.采用组合或聚合复用时,可以将已有对象纳入新对象中,使之成为新对象的一部分,新对象可以调用已有对象的功能,它有以下优点。
-
它维持了类的封装性。因为成分对象的内部细节是新对象看不见的,所以这种复用又称为“黑箱”复用。
-
新旧类之间的耦合度低。这种复用所需的依赖较少,新对象存取成分对象的唯一方法是通过成分对象的接口。
-
复用的灵活性高。这种复用可以在运行时动态进行,新对象可以动态地引用与成分对象类型相同的对象。