您的位置:首页 > 其它

《软件构造》 第五章 基于可复用性的软件构造处理

2018-06-23 15:55 176 查看

》》可复用性

高复用性的软件应具有如下特性:小、简单;与标准兼容;灵活可变;可扩展;泛型、参数化;模块化;变化的局部性;稳定;丰富的文档和帮助

白盒复用:源代码可见,可修改和扩展。复杂度高,需要对内部代码充分了解

黑盒复用:源代码不可见,无法修改代码;简单清晰,适应性差

可复用性外部观察:

——类型可变:能够复用的部分应该类型参数化,以适应不同的数据类型;复用的部分应该一般化;适应不同的类型,且满足LSP(子类一定可以替代父类)

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

——功能分组:提供完备的细粒度操作,保证功能的完整性,不同场景下复用不同的操作( 及其组合)

——表示独立:内部实现可能会经常变化,但客户端不应受到影响。

——共性抽取:将共同的行为(共性)抽象出来,形成可复用实体

LSP:更强的不变量;前置条件更弱;后置条件更强

协变:父类型->子类型:越来越具体specific 返回值类型:不变或变得更具体;异常的类型:也是如此。

反协变、逆变:父类型->子类型:越来越具体specific 参数类型:要相反的变化,要不变或越来越抽象(在java中不允许)

数组的子类型化:

——数组是协变的:一个数组T[ ] ,可能包含了T类型的实例或者T的任何子类型的实例

——即子类型的数组可以赋予父类型的数组进行使用,但数组的类型实际为子类型。

——下面报错的原因是myNumber指向的还是一个Integer[] 而不是Number[]

Number[] numbers = new Number[2];
numbers[0] = new Integer(10);
numbers[1] = new Double(3.14);
Integer[] myInts = {1,2,3,4};
Number[] myNumber = myInts;
myNumber[0] = 3.14; //run-time error!
泛型的子类型化:

泛型的类型是不变的:ArrayList<String> is a subtype of List<String>; List<String> is not a subtype of List<Object>

通配符:? 表示所有满足条件的未知类型 List<Number> is a subtype of List<?> 

List<Number> is a subtype of List<? extends Object> 

List<Object> is a subtype of List<? super String>

委派和组合:

比较器(Comparator):

另一种方法:让你的ADT实现

Comparable
接口,然后
override compareTo()
 方法。与使用
Comparator
的区别:不需要构建新的
Comparator
类,比较代码放在ADT内部。下面为具体例子。


委派(delegation):在一个类中调用另一个类的方法

——显性委派:将发送对象传递给接收对象。

——隐性委派:由语言的成员查找规则。

可以看到,想在B中调用A,需要先委派一个A


CRP(合成复用原则):委派可以看做Object层面的复用机制,而继承可以看做是类的层面

在委派时多使用接口,实例化接口然后重写接口的方法


委派的种类:

——临时性委派(Dependency):最简单的方法,调用类里的方法(use a),其中一个类使用另一个类而不实际地将其作为属性。

——永久性委派(Association):类之中有其它类的具体实例来作为一个变量(has a)。

——更强的委派,组合(Composition):更强的委派。将一些简单的对象组合成一个更为复杂的对象。(is part of)。里面其中一个对象损坏,则组合对象损坏

——聚合(Aggregation):对象是在类的外部生成的,然后作为一个参数传入到类的内部构造器。(has a)


可复用的库和框架:

白盒框架和黑盒框架:白盒一般是继承,黑盒一般是委派、组合

——白盒框架是基于面向对象的继承机制。之所以说是白盒框架,是因为在这种框架中,父类的方法对子类而言是可见的。子类可以通过继承或重写父类的方法来实现更具体的方法。虽然层次结构比较清晰,但是这种方式也有其局限性,父类中的方法子类一定拥有,要么继承,要么重写,不可能存在子类中不存在的方法而在父类中存在。

public abstract class PrintOnScreen {
public void print() {
JFrame frame = new JFrame();
JOptionPane.showMessageDialog(frame, textToShow());
frame.dispose();
}
protected abstract String textToShow();
}
public class MyApplication extends PrintOnScreen {
@Override protected String textToShow() {
return "printing this text on " + "screen using PrintOnScreen " + "white Box Framework";
}
}
——黑盒框架时基于委派的组合方式,是不同对象之间的组合。之所以是黑盒,是因为不用去管对象中的方法是如何实现的,只需关心对象上拥有的方法。这种方式较白盒框架更为灵活,因为可以在运行时动态地传入不同对象,实现不同对象间的动态组合;而继承机制在静态编译时就已经确定好。黑盒框架和白盒框架可以互相转化。
public interface TextToShow {
String text();
}
public class MyTextToShow implements TextToShow {
@Override
public String text() {
return "Printing";
}
}
public final class PrintOnScreen {
TextToShow textToShow;
public PrintOnScreen(TextToShow tx) {
this.textToShow = tx;
}
public void print() {
JFrame frame = new JFrame();
JOptionPane.showMessageDialog(frame, textToShow.text());
frame.dispose();
}
}
》》复用的设计模式

——结构型模式:Structural patterns

适配器模式(Adapter)

装饰器模式(Decorator )

外观模式(Facade)

——行为类模式:Behavioral patterns 

策略模式(Strategy)

模板方法模式(Template method)

迭代器模式( Iterator)

适配器模式:将某个类或接口转换为用户期望的其他形式

实例:问题描述:其中LegacyRectangle是已有的类(需要传入矩形的一个顶点、长和宽),但是与client要求的接口不一致(需要给出对角线两个顶点坐标),我们此时建立一个新的接口Shape以供客户端调用,用户通过Shape接口传入两个点的坐标。Rectangle作为Adapter,实现该抽象接口,通过具体的方法实现适配。  在不适用适配器时:会发生委派不相容。


装饰器模式:为对象增加不同侧面的特性,对每一个特性构造子类,通过委派增加到对象上


Stack s = new ArrayStack(); //构建一个普通的堆栈 UndoStack s = new UndoStack(new ArrayStack()); //构建撤消堆栈 SecureStack s = new SecureStack( new SynchronizedStack( new UndoStack(s)))//构建安全的同步撤消堆栈

外观模式:客户通过一个简化的接口来访问复杂系统内的功能。把多种相似类型的类及其功能用一个类封装起来,通过传参在内部完成选择



客户端代码


策略模式:一个类的行为或算法可以在运行时更改。针对特定任务存在不同的算法,但客户端可以根据动态上下文在运行时切换算法。就是在一个接口下设计多个子类,每个子类有自己的功能算法。在运行时调用接口的不同子类实现不同选择。

模板模式:模板模式中,一个抽象类公开定义了执行它的方法的方式/模式,它的子类可以按照需要重写实现方法,但调用将以抽象类中定义的方法进行。

例子,对于边的定义时,无向边,有向边只需要重写边的方法,或者再增加一些方法。

迭代器模式:这种模式用于顺序访问集合对象的元素,而又无需暴露该对象的内部表示。用途:解决客户需要统一的策略来访问容器中的所有元素,与容器类型无关。实现方法:这种模式让自己的集合类实现Iterator接口,并实现自己的独特

Iterator
迭代器(
hasNext, next, remove
),允许客户端利用这 个迭代器进行显式或隐式的迭代遍历

例子:




阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: