一、 可复用性
两类软件复用:1. 面向复用编程:开发出可复用的软件;2. 基于复用编程:利用已有的可复用软件搭建应用系统。
两类源码级别的复用:
1. 白盒复用:源代码可见,可修改和扩展。
2. 黑盒复用:源代码不可见,不能修改;只能通过API接口来使用。
Liskov替换原则(LSP):更强的不变量、更弱的前置条件、更强的后置条件。
协变:父类到子类越来越具体;返回值类型不变或更具体;异常的类型不变或更具体。
逆变:父类到子类越来越具体;参数类型不变或越来越抽象。
Java不支持逆变;去掉@Override将视为重载。
Java中的数组是协变的。也就是说数组T[]中任意一个元素可以是T的子类。
List<String>不是List<Object>的子类,因为Java实现泛型的方式是“类型擦除”。要实现泛型的子类,可以使用通配符,如List<Number>是List<?>的子类。
委托(delegation):一个对象请求另一个对象的功能,是复用的一种常见形式。
推荐用委托代替继承。
委托的分类:
1. Dependency:临时性delegation,即A use B。
2. Association:永久性delegation,即A has B。
两种特殊的Association:
2.1. Composition:通过类内部初始化委托变量建立的delegation。
2.2. Aggregation:通过客户端调用方法或构造方法,从外部传入delegation类,保存到某个field建立的delegation。
区别Dependency和Association主要看类是否有一个field来保存委托变量。Dependency只是用方法参数等建立delegation,Association通过固有的filed来建立delegation。
Composition和Aggregation的区别:Composition比Association更强,delegation关系无法修改(通过初始化建立);Aggregation比Association更弱,delegation关系可以修改(通过方法或creator,由传入参数建立)。
复合复用原则(CRP)鼓励使用委派而不是继承来实现复用。
白盒框架:通过代码层面的继承进行框架扩展:继承、子类、重载和重写。主要利用继承实现。
黑盒框架:通过实现特定接口/委托进行框架扩展:接口、委托。主要利用委托/组合实现。
二、 可维护性
模块间的联系成为耦合。联系越紧密,耦合性越强。
模块内部元素的联系称为内聚。元素结合得越紧密,内聚性越高。
追求低耦合、高内聚。
面向对象设计原则:SOLID,分别是单一责任原则(SRP)、开放封闭原则(OCP)、Liskov原则(LSP)、接口隔离原则(ISP)、依赖倒置原则(DIP)。
单一责任原则(SRP):一个类应该只有一个引起它变化的原因。也就是说,一个类应该只负责一个职责,若需要修改这个类,也只是因为这个职责的变化才引起了类的修改。
开放封闭原则(OCP):一个实体(类、函数、模块等)应该对外扩展开放,对内修改封闭。某实体应该易于扩展,在扩展某类的功能时应该通过添加新的代码来实现,而不是修改其内部代码。
Liskov替换原则(LSP):任何基类出现的地方子类一定可以出现。
接口隔离原则(ISP):不能强迫客户端依赖于它们不需要的方法和接口,只提供必须的接口。
依赖倒置原则(DIP):一个类依赖另一个类时,应该尽量依赖其接口而不是具体实现。
正则表达式: