欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

软件构造博客(2)

程序员文章站 2022-03-01 15:52:20
...

知识梳理2:

面向对象的编程

对象、类、属性、方法

  • 静态方法不用通过对象调用
  • 静态方法无法调用非静态成员(方法和变量)
  • 实例方法需要通过对象调用

接口和枚举

  • 接口之间可以继承与扩展
  • 一个类可以实现多个接口
  • 一个接口可以有多个实现类

封装和信息隐藏

信息隐藏(或封装):

  • API同实现分离

  • 模块间只通过API通讯

信息隐藏的好处

  • 类之间解耦
  • 加速系统的开发
  • 易于维护
  • 进行有效的性能调整
  • 提高复用性

接口可以做信息隐藏

  • 使用接口类型声明一个变量
  • 客户端仅使用接口中定义的方法
  • 客户端无法直接访问属性

继承和重写

重写

严格继承:子类只能添加新方法,无法重写超类中的方法

Java中用final声明方法表示不能重写

重写时方法的签名须完全一致

抽象类

  • 抽象方法:只有定义没有实现
  • 抽象类:至少有一个抽象方法
  • 抽象类不能实例化
  • 继承某个抽象类的子类实例化时所有父类中的抽象方法必须已经实现

多态、子类型、重载

三种多态

  • 特殊多态(ad hoc 多态)
  • 参数化多态(泛型)
  • 子类型多态(一个变量名可以代表多个类的实例)

特殊多态:一个方法不同的参数列表(Overload,Overload是在编译阶段进行检查,是静态类型检查,与之相反 Override是运行时动态检查)

Override的规则:

  • 必须有不同的参数列表(签名不同)
  • 可以返回不同的类型
  • 可以不同的public/private。。。
  • 可以声明不同的异常
  • 可以在同一个类内重载,也可以在子类中重载

泛型:PlanningEntry 编译时检查

如果类/接口声明了泛型变量,则称为泛型类/接口

泛型接口可以使非泛型的实现类或泛型的实现类

子类型多态:子类型的规约不能弱化超类型的规约

不同类型的对象可以统一的处理而无需区分

ADT和OOP中的等价性

  • 等价关系
  • 引用等价性和对象等价性
  • 可变数据类型的观察等价性和行为等级等价性

重写equals():参数是Object,如果传入其他参数,则不算重写,而是重载

用@Override声明重写,让编译器确保签名的正确性

重写equals:要先进行类型比较和null值判定

instanceof:动态类型检查

除了用于实现equals方法,尽可能避免使用instanceof和getClass()

等价关系

  • 自反、传递、对称
  • 等价的对象,其hashCode()的结果必须一致

可变类型

观察等价性:在不改变状态的情况下,两个mutable对象是否看起来一致

行为等价性:调用对象的任何方法都展示出一致的结果

对于可变类型来说,往往倾向于实现严格的观察等价性 但在有些时候,观察等价性可能导致bug,甚至可能破坏RI

JDK中不同的mutable类型的等价性标准不同

  • Date:观察等价性
  • List:观察等价性
  • StringBuilder:行为等价性

对于可变类型,无需重写这equals和hashCode,直接继承Object的两个方法即可。

如果一定要判断两个可变 对象看起来是否一致,最好定义一个新的方法。

可复用性的度量、形态与外部表现

代码级的复用:

  • 白盒复用:源代码可见,可修改和扩展
  • 黑盒复用:源代码不可见,不能修改

模块级的复用:

类、接口

  • 继承
  • 委托

库级复用:

API、Package

系统级的复用:

框架:黑盒框架、白盒框架

面向复用的软件构造技术

行为子类型与Liskov替换原则 LSP

如果对于类型T的对象x,q(x) 成立,那么对于类型T的 子类型S的对象y,q(y) 也成立

Java子类型中重写的方法不能抛出额外的异常

LSP:

  • 更强的不变量
  • 更弱的前置条件
  • 更强的后置条件

在编程语言中:

  • 前置条件不能强化
  • 后置条件不能弱化
  • 不变量要保持
  • 子类型方法参数:逆变
  • 子类型方法的返回值:协变
  • 异常类型:协变

协变:子类型中的返回值、异常也变成更具体的类型,例如:

Class T {
    Object a(){}
}

Class S extends T {
    @Override
    String a(){}
}

逆变:参数类型越来越抽象

class T {
	void c( String s ) { … }
}
class S extends T {
	@Override
	void c( Object s ) { … }
} 

目前Java遇到这种情况当作Overload对待

Java中的数组是协变的

  • 委托发生在对象层面
  • 继承发生在类层面

组合

Composite Reuse Principle (CRP) 组合是委派的一种形式

  • Dependency:临时的委派

  • Association:永久的委派

  • Composition:更强的association

  • Aggregation:更弱的association

面向复用的设计模式

适配器模式

  • 将某个类/接口转换为client期望的其他形式

装饰器模式

以递归的方式实现

一个接口,定义公共操作

一个起始对象,将通用的方法放入该对象

一个Decorator抽象类,是所有装饰类的基类,具体的装饰类实现具体需要实现的功能

Stack t = new SecureStack( new SynchronizedStack( new UndoStack(s))

装饰器同时使用了继承和委托

Facade 外观模式

提供一个简化的接口供客户端使用

策略模式

有多种不同的算法来实现同一个任务,但需要client根据需要动态切换算法。

模板模式

做事情的步骤一样,但具体方法不同,共性的步骤在抽象类内公共实现,差 异化的步骤在各个子类中实现

使用继承和重写实现模板模式,在框架中用得多

迭代器

可维护性的度量与构造原则

是作业内容,想具体学习建议找其他的博客。

上一篇: ContentResolver

下一篇: ContentResolver