第十、十一章
可维护性的常见度量指标
- 圈/环复杂度
- 代码行数
- Halstead Volume: a composite metric based on the number of (distinct) operators and operands in source code.
- 可维护性指数
- 继承的层次数目
- 类之间的耦合度
- 单元测试覆盖度
聚合度与耦合度
- 耦合度(coupling)
- 衡量模块之间独立性的指标
- 模块间的接口数目和接口的复杂度决定耦合度
- 聚合度(cohesion)
- 衡量模块的功能是否高度集中的指标
- 软件开发中要做到高内聚,低耦合
SOLID
-
单一开放原则(he S ingle responsibility principle)
- 一个ADT应只负责一个功能,不应有多于一个原因让其发生变化
-
开放-封闭原则(the O pen-Closed Principel)
- 多扩展开放,可扩展性强大
- 对修改封闭,模块自身不应当被修改
- 使用继承或者委托的方法实现
反例:public void draw(Shape s)
需要使用多if判断分支
正例:
abstract class Shape{ abstract public void draw(); }
-
Lsp替换原则(the L iskov substitution principle)
-
接口隔离原则(the I nterface segregation principle)
- 不能向客户端暴露他们不需要的接口,避免胖/污染接口
- 对于每一类,尽量减少使用继承的方式继承太多不必要的函数
使用实现接口的形式,将不同功能的组合隔离开,详见上一讲
-
依赖转置原则(the D ependency inversion principle)
- 实现细节应当依赖于抽象,不能使得高层模块依赖于底层模块
- 面向接口编程,而非直接调用底层模块实体
-
总结
- 抽象:用抽象隔离稳定的部分和易于变化的模块
- 分离:大模块变成小模块,减少模块之间的耦合
语法、正则表达式
-
Java中的正则表达式类
Pattern regex = Pattern.compile("Java String regular expression"); Matcher m = regex.matcher("待匹配的字符串") if (m.match()){ m.group(x); //第0号组是整个匹配串 //否则表示正则表达式中的第x个括号 }
-
Java正则表达式的语法规范
- \.的表达必须要是\\.(如同markdown文本)
7中设计模式
-
创建型模式
- factory:虚拟构造器,定义一个用于创建对象的接口,让该接口的子类型来决定实例化哪一个类,从而使一个类的实例化延迟到其子类。
- 实现方式1:定义工厂接口,每个子类的工厂类实现工厂接口(究竟有什么意义,徒劳的增加客户端的体力)
- 实现方法2:只实现一个工厂方法,通过输入的字符串判断
- 实现方式3:静态工厂方法,不必每次都创建新的工厂对象
-
结构模式
- adapter
- 通过对已有的类进行继承封装或者委托封装,实现复用的目的
- decorator
- 适用于多个类的方法名称,数目相同,但是具体实现不同却又相互独立的情况
- 需要实现一个接口,定义这多个类的同名方法
- 需要用一个具体类(被装饰对象)实现接口,实现多个类同名方法的的共同操作其构造函数不需要该接口类型的参数
- 需要定义一个抽象类(装饰物)实现接口,该抽象类使用protected字段委托具体类(被装饰物)进行实现。因此,其构造函数需要一个该接口类型的参数
- 继承抽象类实现具体类(具体的装饰物),不需要继承,只需要重写公用方法即可。在公用方法里必须调用
super.operation()
,并实现自己的逻辑即可
- adapter
-
行为模式
-
strategy
- 适用于一个类需要完成一个行为,完成这个行为有多种确定的途径,但选择权位于client
- 将多种确定途径的共性抽象成多个方便,变成接口
- 该类的该行为方法可以设计成需要上述的一个接口参数,根据接口参数编写行为具体实现步骤
- 实现接口
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0c3bG6SZ-1655085176059)(resource/strategy.JPG)]
-
template
- 适用于算法相同,但是算法的有些步骤是客户定制,有些是不变的
- 定义一个实现该算法/操作的抽象类,将该算法按照固定的流程,分成几个操作
- 对于自定义的操作,在抽象类中体现为
protected
的抽象方法, - 对于固定的步骤可以是
final protected
的实现方法,也可以直接在算法中实现 - 定义一个
final public
的方法用于实现该算法的核心,调用上述步骤完成该方法 - 客户端调用的时候,继承并重写
protected
中的自定义部分,即可使用public
方法
-
iterator
- 适用于客户端想在一套ADT上实现一套 统一操作,不论 这个ADT的 实现
- 更具体说,想要在容器类上的实现统一的遍历操作
- 定义这一套ADT接口和iterator的接口上统一操作
- 在ADT接口中定义一个createIterator的方法,返回一个实现iterator接口的对象
- 在具体实现ADT的时候,同时实现该ADT对应的ConcreteIterator
- 客户端要对具体ADT进行操作的时候,使用
ADT.createIterator
获得ConcreteIteraor
之后使用iterator进行操作即可。
- 适用于想要根据自定义的逻辑操作ADT的数据
- 为ADT预留一个扩展接入点,外部实现的功能代码能够在不改变ADT的前提下通过委托临时接入ADT
- 定义ADT抽象类,和Visitor抽象类
- Visitor要定义一个visitor方法,会接受一个ADT数据类型的参数,这个方法能够被重写
- ADT也要定义一个accept方法,该方法接受一个Visitor,调用其visitor方法,参数是自己
- 客户端使用的时候后通过新建一个Visitor对象,重写其中的visitor方法,然后调用ADT的accept方法,传入自己写的Visitor即可
-