第9-12章在考试中也有不小的占比,并且难度偏高。不过值得高兴的是,我们的学习终于要结束了!
面向复用编程(programming for reuse):开发出可复用的软件;
基于复用编程(programming with reuse):利用已有的可复用软件搭建应用系统。
源代码级别的复用
最主要的复用
以下内容都可能被复用:需求、设计/规约spec、数据、测试用例、文档
·白盒复用:源代码可见,可修改和扩展
·黑盒复用:源代码不可见,不可修改;只能通过API接口来使用
模块级别的复用※
设计可复用类:继承与重写、重载、参数多态性与泛型编程、行为子类化与泛型编程、组合与委托
两种复用类/接口的途径:继承、委托
库级别的复用(API、包)和系统级别的复用(框架)
用子类型可以增加方法,但不可删除方法;
子类型需要实现抽象类型中的所有未实现方法;
子类型中重写的方法不能抛出额外的异常;
协变(co-variance):子类型中重写的方法必须有相同或子类型的返回值或者符合的参数,即返回值/异常类型:不变或更具体;
逆变(contra-variance):子类型中重写的方法必须使用同样类型的参数或者符合的参数,即参数类型:不变或更抽象。(Java不支持逆变)
可以简记如下:
更强的不变量
更弱的前置条件
更强的后置条件
Java中的数组是协变的,也就是说,数组T中任意一个元素可以是T的子类。
Java中,泛型类型是不支持协变的,这是因为发生了类型擦除,运行时就不存在泛型了,所有的泛型都被替换为具体的类型。如ArrayList<String>是List<String>的子类,但是List<String>不是List<object>的子类。
委派是一个对象请求另一个对象的功能,通过运行时动态绑定,实现对其他类中代码的动态复用的过程。
通俗来说就是我在这个类中借用一下你这个对象,让这个对象执行对应类中的方法。我声明这个对象的过程叫组合,我调用对象方法的时候叫委托。
“委托”发生在object层面,“继承”发生在class层面。
首先委托可以分为两类,分别如下:
依赖(Dependency):是临时性的delegation,即A use B。
把被delegation的对象以方法参数方式传入。只有在需要的时候才建立与被委派类的联系,而当方法结束的时候这种关系也就随之断开了。
关联(Association):是永久性的delegation,即A has B。
被delegation的对象保存在rep中,该对象的类型被永久的与此ADT绑定在了一起。
两种方法的区别就在于有没有一个变量去存储那个对象。
然后关联也可以分为两类:
组合(Composition): 更强的association,但难以变化。
就是直接在构造方法里新建一个对应的变量;
聚合(Aggregation): 更弱的association,但可动态变化。
这个就是可以在构造方法中传入一个变量就可以了。
-
-
- 复用复合原则(CRP)
-
CRP鼓励我们多用委托而非继承。
白盒框架主要通过继承实现。
黑盒框架主要通过委托/组合实现。
耦合与内聚
模块之间的联系称为耦合。模块间联系越紧密,耦合越强。
模块内部元素的联系称为内聚。模块内元素结合得越紧密,内聚性越高。
我们追求低耦合、高内聚。
使得ADT变化的原因(责任)不得多于一个,如果多于一个,就分散它们。不符合SRP会导致低内聚、高耦合。
-
-
- 开放封闭原则(OCP)
-
用抽象技术,使得实体对外扩展开放,对内修改封闭。也就是增加新功能时通过添加新的代码来实现,而不是修改其内部代码。
-
-
- Liskov替换原则(LSP)
-
任何父类出现的地方,子类一定可以出现,用来检验继承是否合理。
-
-
- 接口隔离原则(ISP)
-
类型依赖接口时,要使接口最小,防止方法冗余。
-
-
- 依赖倒置原则(DIP)
-
一个类依赖另一个类时,要尽量依赖接口。
此外,对于转义字符\,在Java中要多写一个\,防止被转义。
设计模式共有23种,但我们只需掌握以下几种:
其中装饰器模式、访问者模式是重点。
装饰者模式:大体上就是同一个对象经过不同的装饰函数,使其变成自己想要让它变成的模式;
访问者模式:基本上就是对于自己不同的客户看到自己不同的东西,这样可以定义一个访问接口,分别对于不同的客户设计不同的类去继承这个接口,改造出自己想要的功能;设计完方法后可以再为不同的被访问者设计接受类型,也就是用不同的class替代if-else。
健壮性:在不正确输入下的强度。
正确性:是否按照spec执行,是最重要的质量指标。
健壮性与正确性对比:对外接口倾向于健壮;对内实现倾向于正确。
-
- Java异常的分类
异常全部是Throwable类的子类。
Throwable两个子类Error类和Exception类:
Error一般指与虚拟机相关的问题,如系统崩溃、虚拟机错误、内存空间不足、方法调用栈溢等。
Exception表示程序可以处理的异常,可以捕获且可能恢复。
此外,异常也可分为checked和unchecked类。
在开发阶段的代码中嵌入,检验某些假设是否成立。若成立表示程序运行正常,否则表明存在错误。
·对来自外部的数据源要仔细检查,例如:文件、网络数据、用户输入等;
·对每个函数的输入参数合法性要做仔细检查,并决定如何处理非法输入;
·public方法接受到外部数据时,需要假定这些参数是不安全或不合法的,需要检查这些参数的合法性再传给private方法
SpotBugs 是一款 Java 静态代码分析工具,可以用来debug。
全剧终
The End