当已经考虑了所有的技术细节和限制条件,我们就可以进入设计阶段,设计阶段需要展开和细化分析模型。设计的目的是为了说明一种可以很容易地翻译成程序设计代码的工作解决方案。
设计阶段可以分成两部分:
1、结构设计 这是非常高级的设计,说明在什么地方定义包(子系统),以及包与包之间的相互依赖与通信机制。自然,我们的目标是构建一种清晰而又简单的体系结构,包与包之间的依赖要少,如果可能的话,尽量避免双向的依赖。
2、详细设计 所有的类都应描述足够的细节,来明确规定谁来编码这些类。 UML中的动态模型用于示范类的对象在具体的环境中的行为。
下面我将详细说明。
第一节 结构设计
一个设计良好的体系结构是开发一个可扩展、可改变的系统的基础,程序包所需要关心的是要么处理一个具体的功能区域,要么处理一个具体的技术区域。从技术逻辑中把应用程序逻辑(域类)区分开来是极其重要的,这是为了万一需要修改程序的某一部分而不会对另一部分产生影响:一个目标就是标识并设定包与包之间(例如“子系统”)的相互依赖的规则,并不在包之间创建双向的依赖(为了避免程序包集成的太过紧密),另一个目标是为了表示标准类库的需要。现在可用的应用程序库强调的主要还是在技术领域,比如用户界面,数据库或通信机制等等,但是,我们也同样盼望出现更多的具体的应用程序库。
本案例研究中的程序包或者说是子系统如下:
1、用户界面包(User-Interface) 这些类都是基于 Java AWT包这个Java中用于编写用户界面应用程序的一个标准的类库。这个程序包与商业对象包(Business Object)协作,商业对象包包含了实际上用于储存数据用的类,用户界面包调用商业对象中的方法来取得并向商业对象中插入数据。
2、商业对象包(Business Object) 它包括来自分析模型,比如 BorrowerInformation, Title, Item, Loan等等的讨论域类。 该设计完全地定义了它们的操作并且添加了对于持久性的支持。 商业对象包与数据库包合作,所有的商业对象类都必须从数据库包中的 Persistent类继承而来。
3、数据库包 (Database Package) 数据库包给商业对象包中的另外一个类提供服务,以使它们能够持久的储存信息。在目前的版本,Persistent类将储存它的子类对象到文件系统中的文件中去。
4、实用程序包(Utility Package) 实用程序包包含用于该系统中的另外一个包的服务,现在,该包中只有 ObjId类,它用于引用遍及本系统的持久对象,包括用户界面,商业对象和数据库包。
第二节 详细设计
详细设计描述新的类--在用户界面和数据库包中的类,以及在本分析中描绘的商业对象类以外的人。本类的状态和动态图表使用的是与分析过程中一样的图表,但是它们被定义在更加详细和更高的技术层次,分析过程中的使用案例描述用于验证在设计阶段处理的使用案例,使用序列图表阐明在系统中,每个使用案例是如何在技术上实现的。
数据库包 应用程序必须有持久储存对象,所以必须添加一个数据库层来提供这个服务,为了简单起见,我们把对象作为文件储存在磁盘上,关于存储器的细节就不需要被应用程序所知了,它调用通用操作,比如 store()、update()、delete()和 find()等等,这些都是一个调用 Persistent的类的一部分,所有的类都需要继承 Persistent(持久对象)。
持久性处理中的一个重要的因素就是 ObjId类,它的对象用于引用任何系统中的持久对象 (无论对象是在磁盘上还是已经被读入应用程序中了 )。 ObjId是Object Identity的简写,是一种熟知的技术,用于处理应用程序中的对象引用。 通过使用对象标识,一个对象标识号就能被传递到 Persistent.getObject ( )操作,然后该对象将从持久存储器中取回。 通常,这要通过每个持久类中的 getObject操作来完成,它还要执行必要的类型检查和转换。对象标识号还可以很容易地作为操作的参数被传递 (例如,一个寻找具体对象的搜索窗口可以通过对象标识号传递它的结果到另外一个窗口 )。
ObjId标识系统(用户界面、商业对象和数据库)中所有的包使用的一个常规类,因此它在设计阶段就被放进实用程序包中而不是数据库包中。Persistent类的当前实现还可以不够完善,它的最终目标是可以很容易的改变持久存储器的实现,目前的替代的办法是把对象出存在关系数据库或面向对象数据库中,也可以使用Java中的持久对象支持储存它们。
商业对象包 在设计阶段中的商业对象包基于分析过程中相应的包――讨论域类。类以及它们的相互关系和行为没有变,但是类被描述的更加详细,包括了它们的相互关系和行为如何实现。
一些操作已经被翻译成好几个设计模型中的操作,一些还被改了名称,这都是很正常的,因为分析只是每个类的能力的描绘,而设计则是系统详细的描述,因此设计模型中的所有的操作都必须有定义好的特征和返回值,注意,下面给出了设计与分析的不同。
系统的当前版本不必检查一本书是否及时归还,也不必处理预借书籍的订单,因此Loan和 Reservation类的日期属性就没有实现。
杂志和书的处理过程是完全相同的,除了借期的不同,而且它还不用处理。 在分析中, Magazine和 Book Title子类已经被认为不必要的并且在 Title类中只有一个类型属性指定该书名是否指出一本书或杂志。在以后的应用程序版本中,如果认为有必要的话,这两个简化都可以删除。
分析过程中的状态图表在设计阶段又被细化了,显示在工作系统中状态如何被表示以及被处理。 Title类的设计状态图表如图 6。 其他对象可以通过调用 addReservation ( )和 removeReservation ( )操作来改变 Title的状态,就像这张图表中所显示的那样。
用户界面包 用户界面包总是在其他包之前,在系统中,它给用户提供服务和信息,显然,这个包基于标准的 Java AWT ( Abstract Window Toolkit )类。设计模型中的动态模型已经被分配到 GUI包中,因为所有的与用户的交互作用都是通过用户界面开始的, 此外,我们还选择序列图表来说明动态模型,本使用案例的设计模型的实现都是用细节描述的,包括类中的实际的操作。序列图表实际上是以一系列迭代的形式创建的。在实现(即编码)阶段更多的细节上的发掘会产生更进一步的迭代。 图 7表明 Add Title的结果设计序列图表。
第三节 用户界面设计
在设计阶段,我们使用一个特定活动创建用户界面。
图书馆应用程序中的用户界面是基于本使用案例的,并且已经被分成下列部分,在主窗口上,它的每个部分都已经被给予一个单独的菜单栏:
1、功能 本系统中的主要功能的窗口就是用来借书、还书以及与借书籍的登记工作等。
2、信息 本系统中的查看信息的窗口就是用来收集书名和借书者的信息。
3、维护 维护本系统的窗口用来添加、更新和删除书名、借书者以及书籍。
一般情况下,每个窗口提供一个系统中的服务并且映射到一个使用案例 (即使并不是所有的用户界面都必须从一个使用案例中映射而来), 创建一个成功的用户界面超出本文讨论的范围,读者朋友请参阅文后提供的代码。我以后还会专门辑文探讨这个问题。