5-29

ADT & OOP 等价性

  • 所以对可变类型来说,无需重写这两个函数,直接继承Object的两个方法即可。
  • 如果一定要判断两个可变对象看起来是否一致,最好定义一个新的方法。
  • JDK中不同mutable等价性标准不同(行为等价性 观察等价性)

  • So immutable types must override both equals() and hashCode() .
  • So mutable types should not override equals() and hashCode() at all

  • clone()方法——对象的复制
  • Integer:引用等价性 与int观察等价性不同

Map等数据结构中输入的是int 运行时自动包装成了Integer get方法得到的也是Integer

面向复用的软件构造技术

  • 面向复用编程:给别人复用
  • 基于复用编程:我复用别人
  • 复用其他,需要选取、适配、修改、扩展,可靠性建立在外部基础上(Lab2)

降低成本恶化开发时间 经过更多测试有效稳定 标准化

管理可复用软件库

往往无法直接复用 给出适配


  • Reusability implies some explicit management of build, packaging, distribution, installation, configuration, deployment, maintenance and upgrade issues.

软件构造过程中任何实体可以复用:需求 规约 数据 测试用例 文档 源码等

▪ Source code level: methods, statements, etc
▪ Module level: class and interface
▪ Library level: API
    – Java Library, .jar
▪ Architecture level: framework 框架

白盒复用源码可见 可定制化程度高 但修改需要对内部实现由足够了解,修改会增加软件的复杂度(eg. Template Method)

黑盒复用源码不可见 只可以通过API接口使用无法修改 简单清晰 但适配性差(eg. Observer, Strategy)

源码层面复用:SearchCode

模块层面复用-类与接口:

对类:继承+委派
Delegation is simply when one object relies on another object for some subset of its functionality (one entity passing something to another entity)

库层面复用:API与软件包——库(callfor)与框架(callback)

系统层面复用:框架 开发者根据framework规约自己填入代码 形成完整的系统 是领域知识的服用

  • 库:开发者构造可运行软件实体,其中涉及到对可复用库的调用
  • 框架:Framework作为主程序加以执行,执行过程中调用开发者所写的程序
    • Whitebox frameworks 白盒框架,通过代码层面的继承进行框架扩展
      • 使用方法:由开发者通过override完成定制的功能
    • Blackbox frameworks 黑盒框架,通过实现特定接口/delegation进行框架扩展 委派组合


设计可复用的类

子类型多态:客户端可用统一的方式处理不同类型的对象

LSP法则 里氏法则(重点)

img

img

协变:返回的数据类型“更具体”

逆变:输入的数据类型“更抽象” JAVA中非法(均视为重载)

泛型不是协变的

数组是协变的

类型擦除:
img

对涉及泛型的结构:List Set等 我们只关注外层类的继承关系(MyClass<A> has no relationship to MyClass<B>, regardless of whether or not A and B are related. The common parent of MyClass<A> and MyClass<B> is Object.)


Delegation

如果你的ADT需要比较大小,或者要放入Collections或Arrays进行排序,可实现Comparator接口并override compare()函数。

img

另一种方法:ADT实现Comparable接口,然后override compareTo() 方法(不是Delegation)

img

Delegation:一个对象请求另一个对象的功能,是复用的常见形式。通过运行时动态绑定,实现对其他类中代码的动态复用(先动态绑定(建立链接 内部存储)再功能委派

Lab2的P2中,要复用P1中开发出的Graph完成社交网络相关功能——是Delegation

CRP原则较继承,通常更倾向于使用委派 避免继承造成的大量无用方法

img

  • “委派“——Object层面(动态绑定)
  • “继承”——Class层面

面向共性的ADT设计与编程:

  • 针对局部共性的行为(非全局共性行为),需要设计复杂的中间层的类,形成复杂的继承树,设计复杂
  • 当子类型行为发生变化时,继承树可能要大规模变化

利用接口和delegation编程(CRP):

遵循CRP原则,尽量避免通过继承机制进行面向复用的设计,尽量通过CRP设计两棵继承树,通过delegation实现“事物”和“行为”的动态绑定,支撑灵活可变的复用

Delegation建立方式分类:

  • Dependency: 临时性的delegation,Delegation关系通过方法的参数传递建立起来
  • Association: 永久性的delegation,Delegation关系通过固有的field建立起来
  • Composition: 更强的association,但难以变化;Delegation关系通过类内部field初始化建立起来,无法修改
  • Aggregation: 更弱的association,可动态变化;Delegation关系通过客户端调用构造函数或专门方法建立起来

Delegation关系支持一对多


框架

img

img

img

委派:Framework向配置文件委派获取信息,用户实现配置接口,对方法继承与重写 Framework使用用户重写的内容来委派获取配置信息


面向可维护性的构造

软件维护不仅仅是运维工程师的工作,而是从设计和开发阶段就开始,考虑将来的可维护性

  • eg:模块化 OO设计原则 OO设计模式 基于状态的构造技术 表驱动的构造技术 基于语法的构造技术

可维护性量纲:圈复杂度(不同代码路径数目),代码行数,*可维护性指数,继承层次数,类间耦合度(类的独立程度,尽可能降低类间关联),单元测试覆盖度等

五个评估模块化标准:可分解性、可组合性、可理解性、可持续性、出现异常后的保护。

五个模块化规则:直接映射、尽可能小的接口、尽可能少的接口、显式接口、信息隐藏

(耦合内聚:根据实际需求tradeoff ?*)

img

  • SRP:一个类,一个责任
  • OCP: 对扩展性开放 对修改的封闭(解决方法:抽象技术)
  • LSP
  • ISP: 只提供必需的接口,避免使用“胖”接口
  • DIP:抽象的模块不依赖于具体的模块

img

img


语法驱动构造:正则表达式

这就是形式语言与自动机的东西了

基本语法:
img

  • .:任何单一字符
  • \d:[0-9]等效
  • \w:[a-zA-Z_0-9]等效
  • \s:任何空白符号
  • \., \(, \), ,\*等等

语法结构树:
img

在JAVA中:

  • Pattern是对regex正则表达式进行编译之后得到的结果
  • Matcher:利用Pattern对输入字符串进行解析

img

先Pattern Compile 再Matcher regex.matcher m.matches


  • When an exception occurs:编译器可帮助检查你的程序是否已抛出或处理了可能的异常
  • Errors and Runtime Exceptions are not checked by compiler
  • Unchecked exception: Programming error, other unrecoverable failure (Error + RuntimeException) 子类型从RuntimeException派生,是程序员本身可以解决的漏洞,不建议使用throws声明或try/catch捕获
  • Checked exception: An error that every caller should be aware of and handle 子类型从Exception派生

语句:

  • throw 具体抛出
  • throws 声明里用:表示本方法可能抛出
  • try, catch, finally : 捕获并处理XX异常

checked unchecked判别:

  • 如果客户端可以通过其他的方法恢复异常,那么采用checked exception;
  • 如果客户端对出现的这种异常无能为力,那么采用unchecked exception;
  • 异常出现的时候,要做一些试图恢复它的动作(如提示用户重新读入等)而不要仅仅的打印它的信息。

assert:隔离仓内-正确性 抛出Exception:隔离仓外-健壮性

创建新的异常类

img

语句结构:try-catch-catch-finally

处理:恢复异常/printStackTrace()[IOException类下的方法],也可以传递给Client处理“推卸责任”,但尽量“承担责任”

  • 如果异常发生前曾申请过某些资源,那么异常发生后这些资源要被恰当的清理
posted @ 2024-05-29 08:46  2022113415-罗昊然  阅读(40)  评论(0)    收藏  举报