哈工大 软件构造课程 复习考点总结(第四、五章)

  1. 代码可理解性

  2. 度量
    1. 标识符的平局长度
    2. 命名独特性比例
    3. 代码复杂度
    4. LoC 代码行数
    5. 注释密度(百分比)
  3. 如何书写可理解性代码
    1. 命名规范
    2. 代码行最大长度,文件最大LoC
    3. 注释
    4. 布局:缩进、对齐、空行、分块等
    5. 避免多层嵌套(增加复杂度)
    6. 文件和包的组织
  4. 包的相关原则
    1. REP 复用/发布等价原则

      复用的粒度等价于发布的粒度(发布的都是应被复用的,未发布的不应被复用)

    2. CCP Common Closure Principle 共同封闭原则
      1. 一个包中的所有类针对同一种变化是封闭的
      2. 一个包的变化将会影响到包里所有的类,而不会影响到其他的包
      3. 如果两个类紧密耦合在一起,即二者总是同时发生变化,那么它们应属于同一个包
    3. CRP Common Reuse Principle 共同复用原则
      1. 一个包里的类应被一起复用
      2. 如果复用了其中一个类,那么就应复用所有的类

    总之,尽量把相关性高的类放在一起,对不同类进行合理划分。

     

  5. 代码复用

  1. 可复用组建的形态和层级
    1. 源代码:方法、声明等
    2. 模块:类、接口
    3. 库:API
    4. 系统(结构):framework 框架:一组具体类、抽象类及其之间的连接关系

 

  1. 代码复用的类型:
    1. White box 白盒复用:源代码可见,可修改和扩展

    即,直接复制修改代码。可定制化程度高,但需要充分了解代码。

    1. Black box 黑盒复用:源代码不可见,不能修改

    只能通过API接口使用,无法修改代码。简单、清晰,但适应性差。

     

  2. Frameworks :domain-level reuse 领域复用

    框架:一组具体类、抽象类及其之间的连接关系

    开发者根据framework的规约,填充自己的代码进去,形成完整的系统;

    开发者 增加新代码、对抽象类机型具体化、实现接口;

    Framework作为主程序加以执行,执行过程中调用开发者所写的程序。

    控制反转(inverse of control),控制权由代码转到了外部容器(framework),好处是降低了对象之间的依赖程度,提高灵活性和可维护性。

     

 

  1. External observations of reusability 可复用的外部观察特性
    1. Type variation 类型可变:泛型,且满足LSP
    2. Implementation variation 实现可变:

      ADT有多种不同的实现,提供不同的representations和abstract funtion,但具有同样的specification (pre-condition, post-condition, invariants),从而可以适应不同的应用场景

    3. Routine grouping 功能分组:
    4. Representation independence 表示独立

      内部实现可能会经常变化,但客户端不应受到影响(不变量为true)

    5. Factoring out common behaviors 抽取共性行为

 

  1. LSP (Liskov substitution principle) liskov 替换原则

  1. 子类型可以增加,但不可删除方法
  2. 子类型需要实现抽象类中所有未实现的方法
  3. 子类型中重写的方法必须有相同或子类型的返回值     co-variance:协变
  4. 子类型中重写的方法必须使用同样类型的参数         contra-variance 反协变(逆变)
  5. 子类型中重写的方法不能抛出额外的异常             协变
  6. 同样或更强的不变量
  7. 同样或更弱的前置条件
  8. 同样或更强的后置条件

 

  1. Covariance 协变、Contravariance 反协变,逆变

  1. 协变

父类型->子类型

Spec越来越具体

返回值类型

不变,或更具体

异常类型

不变,或更具体

 

  1. 反协变

父类型->子类型

Spec越来越具体

参数类型

不变,或更抽象(由于java语法,不能更抽象)

 

  1. 注意
    1. 数组( T [ ] )是协变的

      T[ ]中元素必须是T或其子类,否则编译时通过,但运行时会错误。

    2. 泛型 不变(类型擦除)

       

  2. 通配符 <?>

    调用时使用。

 

  1. Comparator and Comparator

对自定义ADT(Edge为例)比较大小,或要放入collections或arrays进行排序

  1. 创建比较类EdgeCompare实现comparator接口

    Collections . sort ( Lsit <Edge> , EdgeCompare)

  2. Edge类实现Comparable接口

    类内ouvrride compareTo 方法

     

     

  3. Delegation 委派

一个对象请求另一个对象的功能

如果子类只需要复用父类中的一小部分方法,可以不需要使用继承,而是通过委派机制实现。

即,一个类不需要继承另一个类的全部方法,通过委派机制调用部分方法。

 

"委派"发生在object层面,"继承"发生在class层面

 

委派的类型

  1. Dependency 依赖 临时的委派 (B uses A)

    类内调用

    A类是B类中的(某中方法的)局部变量;

A类是B类方法当中的一个参数;

A类向B类发送消息,从而影响B类发生变化;

  1. Association 关联 永久的委派 (B owns A) (关联关系可以是双向的)

    A类为B的成员变量(或者对象数组)。

    也可能自关联(如,自身的成员变量有自身的实例,如父节点有子节点)

  2. Composition 组合 更强的委派 (A is part of B )

    A是B的一部分,B不能脱离A存在,A不能单独存在。

     

  3. Aggregation 聚合

    整体和部分(可有可无)的关系。

     

     

    1. CRP (Composite Reuse Principle)组合复用原则

    对于某一具体行为,用委派代替继承。

    使用接口定义不同方面的行为,

    接口之间通过extends实现行为的组合(组合多用接口,则组合接口汇集了其他接口的行为)。

    用具体类实现组合接口。

     

    1. White box and black box framework 白盒框架和黑盒框架
       

      白盒框架

      黑盒框架

      实现方式

      通过 子类 和 重写方法 实现扩展

      继承

      通过实现 插件接口 实现扩展

      委派/组合

      常用设计模式

      模板方法

      策略模式 观察者模式

      调用机制

      子类型有main方法,但framework拥有控制权

      插件加载机制加载插件(委派),framework拥有控制权

      另一种实现

      在抽象父类中添加abstract方法

      (需修改framework代码)

      子类实现abstract方法

      实现预留接口

      (不需修改framework代码,framework中有预留接口)

      实现类实现接口

       

      例如

      Class WhiteRun extends Thread{

      (override run) }

      New WhiteRun().strat

      例如

      Class BlackRun implements Runnable

      New Thread( new BlackRun() ).start()

       

设计模式

Structural patterns 结构型设计模式

  1. Adapter 适配器模式

将某个类/接口 转换为client期望的其他形式(client的调用传参与类/接口 方法的参数列表不一致,不兼容)

 

增加一个接口,将已存在的子类封装

Client面向接口编程,从而隐藏具体子类。

 

适配器类实现接口或继承实现接口的父类,

适配器中调用子类方法实现功能(委派)。

 

可能client调用子类方式(如参数形式等)与子类不匹配,

通过适配器进行调整调用,适配子类,从而实现原本不兼容的调用

 

  1. Decorator 修饰器

为对象增加不同侧面的特性。

 

对每一个特性构造子类,通过委派机制增加到对象上。

例如:Collections.synchronizedList( List<T> list)

即返回一个在list增加了新特性的对象。

 

即为对象本身和其需要增加的特性进行封装,

基础功能通过委派(父类)实现,并额外增加新特性,成为一个新的类。

Client可以通过层层修饰获得具有多种特性的对象。

 

  1. Façade 外观模式

 

客户端需要通过一个简化的接口来访问复杂系统内的功能。

 

提供一个统一的接口来取代一系列小接口调用,相当于对复杂系统进行封装,简化客户端使用。

 

 

Behavioral patterns 行为类设计模式

  1. Strategy 策略模式

对一个任务,有多用算法实现。

 

为该任务创建一个接口,

实现类实现同一接口中的方法。

 

  1. Template method 模板模式

做事情的步骤一样,但具体方法不同。

 

共性的步骤在抽象类内公共实现,差异化的步骤在各个子类中实现。

使用继承和重写实现模板模式。

(实验中的 GoncreteGraph)

 

模板模式广泛应用于framework。

 

  1. Iterator 迭代器

独立于元素类型,访问容器内的所有元素。

 

 

 

 

 

 

Iterator pattern:让自己的集合类实现Iterable接口,并实现自己独特的iterator迭代器(hasNext,next,remove),允许客户端利用这个迭代器进行显示或隐式的迭代遍历。

 

(实现了iterable的对象才可用foreach遍历)

for(E e : collection) { …}

 

Iterator<E> iter = collection.iterator();

While(iter.hasNext()) {…}

猜你喜欢

转载自www.cnblogs.com/standingby/p/9213569.html