子曰:”面向接口进行开发,而不是面向实现;依赖于抽象类型,而不是具体类。”
0.前置知识(UML图)
0.1 依赖(教授——>课程,教授依赖于课程资料):如果修改一个类的定义可能会造成另一个类的变化,那么这两个类之间就存在依赖关系。(在一个类中调用另一个类)。对类 B 进行修改会影响到类 A 。
0.2 关联(教授====>学生,教授与学生进行交流):
关联可视为一种特殊类型的依赖,即一个对象总是拥有访问与其交互的对象的权限,而简单的依赖关系并不会在对象间建立永久性的联系。对象 A 知道对象 B。类 A 依赖于类 B。
0.3 聚合(院系<>====>教授,院系包含教授,还有其他的东西):
在聚合关系中,一个对象拥有一组其他对象,并扮演着容器或集合的角色。组件可以独立于容器存在,也可以同时连接多个容器。对象 A 知道对象 B 且由 B 构成。类 A 依赖于类 B。
0.4 组合(大学<=>====>院系,大学由院系构成,院系不能脱离大学而存在):
组合是一种特殊类型的聚合,其中一个对象由一个或多个其他对象实例构成。组合与其他关系的区别在于组件仅能作为容器的一部分存在。对象 A 知道对象 B、由 B 构成而且管理着 B 的生命周期。类 A 依赖于类 B。
0.5 设计模式分类
创建型模式:提供创建对象的机制,增加已有代码的灵活性和可复用性。
结构型模式:介绍如何将对象和类组装成较大的结构,并同时保持结构的灵活和高效。
行为模式:负责对象间的高效沟通和职责委派。
下面有一个例子,解释了为什么子曰:”通过接口与对象交互要比依赖于其具体类的好处更多。”
这个过程是一个不断解耦合的过程,刚开始所有类紧密耦合,代码复用性极差。之后采用了多态的方法,但是公司的某些方法(createsoftware())仍然依赖于具体的员工。于是,我们又提供了一个getemployee()的接口,雇员对象将在具体公司子类中创建。这下公司基类彻底与员工解耦合了。
1.组合优于继承
组合是代替继承的一种方法。继承->(汽车是交通工具),组合->(汽车有一个引擎).
下面看一个实例
在多个维度上扩展一个类(汽车类型X引擎类型X驾驶类型)可能导致子类组合爆炸。
这时,我们需要用到组合:将不同“维度”的功能抽取到各自的类层次结构中。
2.SOLID原则
2.1 Single Responsibility Principle(单一职责原则):尽量让每个类只负责软件中的一个功能,并将该功能完全封装(你也可称之为隐藏)在该类中。
2.2 Open/closed Principle(开闭原则):本原则的主要理念是在实现新功能时能保持已有代码不变。对于扩展,类应该是“开放”的;对于修改,类则应是“封闭”的。
2.3 Liskov Substitution Principle(里氏替换原则):当你扩展一个类时, 记住你应该要能在不修改客户端代码的情况下将子类的对象作为父类对象进行传递。这意味着子类必须保持与父类行为的兼容。在重写一个方法时,你要对基类行为进行扩展,而不是将其完全替换。
子类方法的参数类型必须与其超类的参数类型相匹配或更加抽象。
子类方法的返回值类型必须与超类方法的返回值类型或是其子类别相匹配。