Programing for/with reuse
编程复用
白盒复用
White box reuse
Reuse of code when code itself is available. Usually requires some kind of modification or adaptation
代码本身可用时复用代码,通常需要一些修改和改变
黑盒复用
Reuse in the form of combining existing code by providing some “glue”, but without having to change the code itself - usually because you do not have access to the code
通过提供一些“粘合剂”以组合现有代码的形式重用,但无需更改代码本身 - 通常是因为无法访问代码
复用类不能取消继承的属性和方法,委派的方法复用
应用框架是包含了接口、抽象类和具体类的可复用程序,使用时需要 在其基础上补充所需要的设计元素。
Whiteboxframeworks:
白盒框架
通过继承和动态绑定实现可扩展性,通过继承框架基类并重写预定义的钩子方法来扩展 现有功能
Blackbox frameworks
通过定义符合特定接口的组件来重用现有功能,这些组件通过委托与框架集成
可复用类的开发者角度:从各种大量的变化中提取出通用的共性的行为 加以复用
Liskov Substitution Principle 替换子类原则
子类型可以添加但不能删除方法
- 具体类必须实现所有未定义的方法
- 重写方法必须返回相同的类型或子类型
- 重写方法必须接受相同的参数类型
- 重写方法可能不会抛出其他异常
- Same or stronger invariants 相同或更强的表示不变量
– Same or stronger postconditions for all methods 相同或更强的后置条件
– Same or weaker preconditions for all methods 相同或更弱的前置条件
型变是指当子类型关系出现在更加 复杂类型中时,如何处理新类型中的子类型关系
Covariant(协变): Subtyping is preserved. If List is a subtype of List. 保持子类型关系
Contravariant(逆变): Subtyping is reversed. If List is a subtype of List. 反转了子类型关系
Invariant(不变): Neither List nor Listis a subtype of the other. 没有子类型关系
三种类型关系如图
Java中的泛型是不“型变”的
ArrayList is a subtype of List – List is not a subtype of List
Wildcards(通配符) – e.g. List<?> or List<? extends Animal> or List<? super Animal>
List is a subtype of List<? extends Animal>
List is a subtype of List<? super Cat>
虚拟机中没有泛型类型对象-所有对 象都属于普通类!
泛 型信息只存在于编译阶段,在运行时会被”擦除”
定义泛型类型时,会自动提 供一个对应的原始类型(非泛型类型),原始类型的名字就是去掉类型参数后的 泛型类型名。
类型变量会被擦除,替换为限定类型,如果没 有限定类型则为Object类型。
实际情况如图
运行时类型查询 只适用于原始类型
应该用getclass方法进行比较
If a parameterized type represents a T producer, use<? extends T>, e.g., get()
参数类型为extend可以用get方法
– If a parameterized type represents a T consumer, use<? super T>, e.g., add()
参数类型为represent可以用add方法
继承表如图
委托是指一个对象依赖于另外一个对象的部分功能
委托可看做是在实体之间共享代码和 数据的低层机制
关联关系:对象类之间的持久关系,允许一个对象实例使另一个对象实例代表它执行操作。
这种关系是结构性的,因为它指定一种对象连接到另一种对象而不表示行为
对象需要其他对象(供应商)实现的临时关系
继承/泛化inheritance:一般与特殊的关系——is a kind of
▪ 组合composition:部分与整体的关系,彼此不可分——is part of
▪ 聚合aggregation:部分与整体的关系,但彼此可分——owns a
▪ 关联association:对象之间的长期静态联系——has a
▪ 依赖dependence:对象之间的动态的、临时的通信联系——use a
▪ 类间联系的强度:继承>>> 组合>> 聚合>> 关联>>> 依赖
定义关键抽象和接口
定义对象不变量和方法
Whiteboxframeworks - 通过子类化和重写方法扩展 - 通用设计模式:模板方法 - 子类具有主要方法但是控制框架
Blackbox框架 - 通过实现插件接口扩展 - 通用设计模式:策略,观察者 - 插件加载机制加载插件并控制框架
Whitebox框架使用子类 - 允许扩展每个非私有方法 - 需要理解超类的实现 - 一次只有一个扩展 - 编译在一起 - 通常所谓的开发者框架
Blackbox框架使用组合 - 允许扩展接口中公开的功能 - 只需要了解接口 - 多个插件 - 通常提供更多模块化 - 可以单独部署(.jar,.dll,…) - 通常所谓的最终用户框架,平台
EMPTY_SET, EMPTY_LIST, EMPTY_MAP – Immutable constants 不支持add操作
▪ singleton(E o) 返回只包含指定对象的不可变集
– Immutable set with specified object
▪ nCopies(int n, T o) 返回由指定对象n个副本构成的不可变List。 – Immutable list with n copies of object
向上兼容/向前兼容(forward),站在旧版软件 的立场,基于旧方法编写的软件不经修改就能在新版环境中运行
向后兼容/向下兼容(downward),站在新版 本的立场讨论对过去版本的兼容性问题,新版软件中可以支持旧版中 的方法
接下来我们看本章最后一节内容:
设计模式adapter、decorator、 façade、strategy、template、 iterator/iterable
Adapter Pattern 适配器模式
意图:将类的接口转换为客户端期望的另一个接口
解决类之间接口不兼容的问题
为已有的类提供新的接口
目标:对旧的不兼容组件进行包装,在新系统中使用旧 的组件
The Adaptee is the existing class.
存在的类
▪ The ITargetis the interface defined in the existing library. 存在库中的接口
▪ The Adapter is the class that you create, it is inherited from the adaptee class and it implements the ITarget interface. 自己创建的类,他被存在的类继承并实施接口
Notice that it can call the SpecificRequest method(inherited from the adaptee) inside its request method(implemented by the ITarget).注意到它可以调用adaptee的方法
通过增加额外的间接层来解决不 协调/不兼容的问题
实例如图
Decorator 装饰边框与被装饰物的一致性
需要对对象进行任意或者动态的扩展组合
方案: 实现一个通用接口作为要扩展的对象,将 主要功能委托给基础对象(stack),然后添加功能(undo,secure,…)。
以递归的方式实现
接口:定义装饰物执行的公共操作
起始对象,在其基础上增加功能(装饰),将通用的方法放 到此对象中。
例子如下图
抽象类是所有装饰类的基类,里面包含的成员变量 component 指向了被装饰的对象。
ConcreteDecoratorclass是可以添加功能的实际装饰器类。 您可以拥有任意数量的ConcreteDecoratorclass,每个都代表一个可以添加的功能
具体实例如图
Façade [fəˈsɑːd] 外观模式
调用者需要一个简化的接口 来调用复杂系统的整体功能。
.
提 供更高层次的接口来使子系统易于使用。
Strategy 整体地替换算法
针对特定任务存在多种算法,调用者需要根据上下文环境动 态的选择和切换
定义一个算法的 接口,每个算法用一个类来实现,客户端针对接口编写程序
Template Method 样板方法
不同的客户端具有相同的算法步骤 ,但是每个步骤的具体实现不同。
在父类中定义通用逻辑和各步骤的抽 象方法声明
子类中进行各步骤的具体实现
在父类声明一个通用逻辑
模板模式用继承+重写的方式实现算法的 不同部分。
策略模式用委托机制实现不同完整算法 的调用(接口+多态)
框架实现了算 法的不变性
客户 端提供每步的具体实现
Iterator Pattern
迭代器模式
问题:客户端需要以统 一的、与元素类型无关的方式访问容器中的所有元素
一种面向迭代的策略模式
隐藏了容器的内部 实现
用统一的接口 支持多种遍历策略
定义迭代器接口
实现迭代功能
Aggregate interface 定义客户端的方法。 它定义的方法允许客户端代码不被关于如何遍历集合的细节所困扰
concreteAggregate类实现Aggregate接口,并且是创建ConcreteIterator的类
下图返回实现iterator接口的类
以上为第五章的内容,主要讲解了
Programing for/with reuse ▪ LSP ▪ 泛型的子类型化 ▪ 泛型中的通配符 ▪ Delegation ▪ Comparator和Comparable
▪ 接口的组合 ▪ 白盒框架的原理与实现 ▪ 黑盒框架的原理与实现 ▪ 设计模式adapter、decorator、 façade、strategy、template、 iterator