《设计模式》刘伟 实验参考答案

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

《设计模式》刘伟 实验参考答案
实验 1
1.在某图形库 API 中提供了多种矢量图模板,用户可以基于这些矢量图创建不同的显示图形,图形库设计人员设计的初始类图如下所示:
在该图形库中,每个图形类(如 Circle 、Triangle 等)的 init()方法用于初始化所创建的图形, setColor()方法用于给图形设置边框颜色,fill()方法用于给图形设置填充颜色,setSize() 方法用于设置图形的大小,display()方法用于显示图形。

客户类(Client)在使用该图形库时发现存在如下问题:
① 由于在创建窗口时每次只需要使用图形库中的一种图形,因此在更换图形时需要修改客户类源代码;
② 在图形库中增加并使用新的图形时需要修改客户类源代码;
③ 客户类在每次使用图形对象之前需要先创建图形对象,有些图形的创建过程较为复杂,导致客户类代码冗长且难以维护。

现需要根据面向对象设计原则对该系统进行重构,要求如下:
① 隔离图形的创建和使用,将图形的创建过程封装在专门的类中,客户类在使用图形时无须直接创建图形对象,甚至不需要关心具体图形类类名;
② 客户类能够方便地更换图形或使用新增图形,无须针对具体图形类编程,符合开闭原则。

绘制重构之后的类图并说明在重构过程中所运用的面向对象设计原则。

参考答案:
Circle
+ + + + +
init () setColor () fill () setSize () display () : void void : void : void : void
: Triangle
+ + + + +
init () setColor () fill () setSize () display () void
: : void void : void : void
: Rectangle + + + + +
init () setColor () fill () setSize () display () void
: void : : void : void : void
Client
2.使用简单工厂模式设计一个可以创建不同几何形状(Shape),如圆形(Circle)、矩形 (Rectangle)和三角形(Triangle)等的绘图工具类,每个几何图形均具有绘制draw()和擦除erase()
两个方法,要求在绘制不支持的几何图形时,抛出一个 UnsupportedShapeException 异常,绘制类图并编程模拟实现。

参考答案:
3. 现需要设计一个程序来读取多种不同类型的图片格式,针对每一种图片格式都设计一个图片读取器(ImageReader),如 GIF 图片读取器(GifReader)用于读取 GIF 格式的图
ShapeFactory
createShape (String type): Shape
+ Circle + +
draw () erase () : void : void
Triangle + +
draw () erase () : void
void
: Shape + +
draw () erase () : void : void
Rectangle + +
draw () erase () : void
: void
UnsupportedShapeException
(
+ UnsupportedShapeException String message)
片、JPG 图片读取器(JpgReader)用于读取 JPG 格式的图片。

图片读取器对象通过图片读取器工厂 ImageReaderFactory 来创建,ImageReaderFactory 是一个抽象类,用于定义创建图片读取器的工厂方法,其子类 GifReaderFactory 和 JpgReaderFactory 用于创建具体的图片读取器对象。

试使用工厂方法模式设计该程序,绘制类图并编程模拟实现。

需充分考虑系统的灵活性和可扩展性。

参考答案:
4. 某软件公司欲开发一套界面皮肤库,可以对桌面软件进行界面美化。

不同的皮肤将提供视觉效果不同的按钮、文本框、组合框等界面元素,其结构如下图所示:
该皮肤库需要具备良好的灵活性和可扩展性,用户可以自由选择不同的皮肤,开发人员可以在不修改既有代码的基础上增加新的皮肤。

试使用抽象工厂模式设计该皮肤库,绘制类图并编程模拟实现。

参考答案:
<< c reate >>
<< c reate >>
GifReaderFactory
createImageReader (): ImageReader
+ ImageReaderFactory
createImageReader (): ImageReader
+ GifReader + readImage (): void
ImageReader + readImage (): void
JpgReaderFactory
+ createImageReader (): ImageReader
JpgReader + readImage (): void
5.使用单例模式的思想实现多例模式,确保系统中某个类的对象只能存在有限个,例如两个或三个,设计并编写代码实现一个多例类。

参考答案:
Multiton
- array : Multiton[]
- Multiton ()
+ getInstance () : Multiton
+ random () : int
多例模式(Multiton
必须自行创建和管理实例,并向外界提供自己的实例,可以通过静态集合对象来存储这些实
例。

多例类Multiton 的代码如下所示:
import java.util.*;
public class Multiton
{
//定义一个数组用于存储四个实例
private static Multiton[] array = {new Multiton(), new Multiton(), new Multiton(), new Multiton()};
//私有构造函数
private Multiton()
{
}
//静态工厂方法,随机返回数组中的一个实例
public static Multiton getInstance()
{
}
return array[random()];
}
//随机生成一个整数作为数组下标
public static int random()
{
Date d = new Date();
Random random = new Random();
int value = Math.abs(random.nextInt());
value = value % 4; return value;
} public static void main(String
args[])
{
Multiton m1,m2,m3,m4;
m1 = Multiton.getInstance();
m2 = Multiton.getInstance();
m3 = Multiton.getInstance();
m4 = Multiton.getInstance();
System.out.println(m1==m2);
System.out.println(m1==m3);
System.out.println(m1==m4);
}
6. 使用单例模式设计一个多文档窗口(注:在Java AWT/Swing 开发中可使用
JDesktopPane 和JInternalFrame 来实现),要求在主窗体中某个内部子窗体只能实例化一次,即只能弹出一个相同的子窗体,如下图所示,编程实现该功能。

(注:用C#或C++实现类似功能也可以)参考答
案:
SubFrame 类充当单例类,在其中定义了静态工厂方法getFrame()。

代码如下所示:
desktopPane.remove(iFrame); }
iFrame=SubFrame.getFrame(); desktopPane.add(iFrame); }
} public static void main(String[] args)
{ new MainClass(); } }
SubFrame 类是 JInternalFrame 类的子类,在 SubFrame 类中定义了一个静态的 SubFrame 类型的实例变量,在静态工厂方法 getFrame()中创建了 SubFrame 对象并将其返回。

在 MainClass 类中使用了该单例类,确保子窗口在当前应用程序中只有唯一一个实例,即只能弹出一个子窗口。

实验 2
1. 现有一个接口 DataOperation 定义了排序方法 sort(int[]) 和查找方法 search(int[], int),已知类 QuickSort 的 quickSort(int[])方法实现了快速排序算法,类 BinarySearch 的 binarySearch(int[], int)方法实现了二分查找算法。

试使用适配器模式设计一个系统,在不修改源代码的情况下将类 QuickSort 和类 BinarySearch 的方法适配到 DataOperation 接口中。

绘制类图并编程实现。

(要求实现快速排序和二分查找,使用对象适配器实现)参考答案:
2. Windows Media Player 和 RealPlayer 是两种常用的媒体播放器,它们的 API 结构和调用方法存在区别。

现在你的应用程序需要支持这两种播放器 API ,而且在将来可能还需要支持新的媒体播放器,请问如何设计该应用程序?绘制类图并编程模拟实现。

OperationAdapter - - sortObj searchObj QuickSort : : BinarySearch
+ + +
OperationAdapter (QuickSort sortObj, BinarySearch searchObj) sort (int array[]) search (int array[], int key) : [] int : int
DataOperation
+ + sort (int array[]) search (int array[], int key) int []
: : int
QuickSort
+ + + +
quickSort (int array[]) sort (int array[], int p, int r) partition (int a[], int p, int r) swap (int a[], int i, int j) []
int : void : int : void
: BinarySearch
+ binarySearch (int array[], int key): int
Client
参考答案:
可使用适配器模式和抽象工厂模式,参考类图如下所示:
在该类图中,为两种不同的播放器提供了两个具体工厂类 MediaPlayerFactory 和
RealPlayerFactory ,其中 MediaPlayerFactory 作为 Windows Media Player 播放器工厂,可以创建 Windows Media Player 的主窗口(MediaPlayerWindow)和播放列表(MediaPlayerList)(为了
简化类图,只列出主窗口和播放列表这两个播放器组成元素,实际情况下包含更多组成元素); RealPlayerFactory 作为 RealPlayer 播放器工厂,创建 RealPlayer 的主窗口 (RealPlayerWindow)和播放列表(RealPlayerList),此时可以使用抽象工厂模式,客户端针对抽象工厂 PlayerFactory 编程,如果增加新的播放器,只需增加一个新的具体工厂来生产新产品族中的产品即可。

由于需要调用现有 API 中的方法,因此还需要使用适配器模式,在具体产品类如 MediaPlayerWindow 和 MediaPlayerList 调用 Windows Media Player API 中的方法,在 RealPlayerWindow 和 RealPlayerList 中调用 RealPlayer API 中的方法,实现对 API 中方法的适配,此时具体产品如 MediaPlayerWindow 、RealPlayerWindow 等充当适配器,而已有的 API 如 MediaPlayerAPI 和 RealPlayerAPI 是需要适配的适配者。

MediaPlayerWindow
MainWindow
MediaPlayerFactory
+ +
createMainWindow () createPlayerList () MainWindow : PlayerList
: PlayerFactory
+ + createMainWindow () createPlayerList () : MainWindow : PlayerList
ClientClass
RealPlayerFactory + +
createMainWindow () createPlayerList () MainWindow
: : PlayerList
RealPlayerWindow
MediaPlayerList
PlayerList
RealPlayerList
MediaPlayerAPI
RealPlayerAPI
3. 使用组合模式设计一个杀毒软件(AntiVirus)的框架,该软件既可以对某个文件夹
(Folder)杀毒,也可以对某个指定的文件(File)进行杀毒,文件种类包括文本文件 TextFile 、图片文件 ImageFile 、视频文件 VideoFile 。

绘制类图并编程模拟实现。

参考答案:
4. 某教育机构组织结构如下图所示:
在该教育机构的 OA 系统中可以给各级办公室下发公文,试采用组合模式设计该机构的组织结构,绘制相应的类图并编程模拟实现,在客户端代码中模拟下发公文。

参考答案:
参考类图如下所示:
fileList
AbstractFile
{ a bstract}
+ + + +
add (AbstractFile file) remove (AbstractFile file) getChild (int i) killVirus () void
: : void AbstractFile : : void
ImageFile
name: String
- + + + + +
ImageFile (String name) add (AbstractFile file) remove (AbstractFile file) getChild (int i) killVirus () void : : void AbstractFile : void
: Folder
- - fileList name ArrayList : String : + + + + +
Folder (String name) add (AbstractFile file) remove (AbstractFile file) getChild (int i) killVirus () : void void : : AbstractFile : void
TextFile
- name: String
+ + + + +
TextFile (String name) add (AbstractFile file) remove (AbstractFile file) getChild (int i) killVirus () void : : void AbstractFile : void
: VideoFile
name: String
- + + + + +
VideoFile (String name) add (AbstractFile file) remove (AbstractFile file) getChild (int i) killVirus () void : : void : AbstractFile void
: 北京总部
教务办公室 湖南 分校 行政办公室
长沙教学点 湘潭教学点 教务办公室 行政办公室
教务办公室 行政办公室 教务办公室 行政办公室
本实例使用了安全组合模式,Unit 充当抽象构件角色,Office 充当叶子构件角色,
Institution 充当容器构件角色。

本实例代码如下所示:
list
Unit
{ a bstract}
+ handleArchives (): void
Office
name: String
- + +
Office (String name) handleArchives () : void
Institution
- - list name : ArrayList : String
+ + +
Institution (String name) add (Unit unit) handleArchives () : void : void
5.某软件公司为新开发的智能手机控制与管理软件提供了一键备份功能,通过该功

可以将原本存储在手机中的通信录、短信、照片、歌曲等资料一次性全部拷贝到移动存储介质(例如MMC 卡或SD 卡)中。

在实现过程中需要与多个已有的类进行交互,例如通讯录管理类、短信管理类等,为了降低系统的耦合度,试使用外观模式来设计并编程模拟实现该一键备份功能。

参考答案:
参考类图如下所示:
其中,OneKeyBackup 充当外观角色,ContactManager 、MessageManager 和 FileManager 充当子系统角色。

6. 某信息系统需要提供一个数据处理和报表显示模块,该模块可以读取不同类型的文件中的数据并将数据转换成 XML 格式,然后对数据进行统计分析,最后以报表方式来显示数据。

由于该过程需要涉及到多个类,试使用外观模式设计该数据处理和报表显示模块。

考虑到有些文件本身已经是 XML 格式,无须进行格式转换,为了让系统具有更好的扩展性,在系统设计中可以引入抽象外观类。

参考答案:
实验 3
1. 在某应用软件中需要记录业务方法的调用日志,在不修改现有业务类的基础上为每一个类提供一个日志记录代理类,在代理类中输出日志,例如在业务方法 method()调用之前输出“方法 method()被调用,调用时间为 2014-11-5 10:10:10”,调用之后如果没有抛异常则输出“方法 method()调用成功”,否则输出“方法 method()调用失败”。

在代理类
OneKeyBackup - - -
cm mm fm ContactManager : MessageManager : : FileManager + click (): void
ContactManager + backup (): void
MessageManager + backup (): void
FileManager + backup (): void
AbstractFacade
abstract} { + ()
execute XMLFacade + execute ()
ExtendedFacade + execute ()
FileOperation + read ()
XMLDataConvertor + convert ()
ReportDisplay + display ()
DataAnalysis ()
+ handle
中调用真实业务类的业务方法,使用代理模式设计该日志记录模块的结构,绘制类图并编程模拟实现。

参考答案:
2. 某软件公司承接了某信息咨询公司的收费商务信息查询系统的开发任务,该系统
的基本需求如下:
(1) 在进行商务信息查询之前用户需要通过身份验证,只有合法用户才能够使用该查询系统;
(2) 在进行商务信息查询时系统需要记录查询日志,以便根据查询次数收取查询费
用。

该软件公司开发人员已完成了商务信息查询模块的开发任务,现希望能够以一种松耦合的方式向原有系统增加身份验证和日志记录功能,客户端代码可以无区别地对待原始的商务信息查询模块和增加新功能之后的商务信息查询模块,而且可能在将来还要在该信息查询模块中增加一些新的功能。

试使用代理模式设计并编程模拟实现该收费商务信息查询系统。

【提示:使用保护代理和智能引用代理】参考答案:
BusinessClass method (): void
+ AbstractLog
+ method (): void
LoggerProxy
- business: BusinessClass + +
LoggerProxy () method () : void
Client
3. 某企业的 SCM(Supply Chain Management ,供应链管理)系统中包含一个采购审批子系统。

该企业的采购审批是分级进行的,即根据采购金额的不同由不同层次的主管人员来审批,主任可以审批 5 万元以下(不包括 5 万元)的采购单,副董事长可以审批 5 万元至 10 万元(不包括 10 万元)的采购单,董事长可以审批 10 万元至 50 万元(不包括 50 万元)的采购单,50 万元及以上的采购单就需要开董事会讨论决定。

如下图所示:
参考答案:
ProxySearcher - - - searcher validator logger : RealSearcher AccessValidator : Logger : + + +
doSearch () validate () log () String : boolean : void
: Searcher
+ doSearch (): String
RealSearcher doSearch (): String
+ AccessValidator + validate (): boolean
Logger + log (): void
4. 某公司欲开发一个软件系统的在线文档帮助系统,用户可以在任何一个查询上下文
中输入查询关键字,如果当前查询环境下没有相关内容,则系统会将查询按照一定的顺序转发给其他查询环境。

基于上述需求,试采用职责链模式对该系统进行设计。

参考答案:
5. 房间中的开关就是命令模式的一个实例,现用命令模式来模拟开关的功能,可控制对象包括电灯和电风扇,绘制相应的类图并编程模拟实现。

参考答案:
参考类图如下所示:
successor
Approver
abstract}
{ # # successor name : Approver
:
String
+ + +
A
p prover (String name)
setSuccessor (Approver successor)
processRequest (PurchaseRequest request) : void : void
Director
+ +
Director (String name)
processRequest (PurchaseRequest request): void
Congress
+ +
Congress (String name)
processRequest (PurchaseRequest request): void
PurchaseRequest
- - -
amount number purpose : double : int : String
+ + + + + + +
PurchaseRequest (double amount,
int number, String purpose) setAmount (double amount)
getAmount ()
setNumber (int number)
getNumber ()
setPurpose (String purpose)
getPurpose ()
: void
double : : void : int : void :
String
VicePresident
+ +
VicePresident (String name)
processRequest (PurchaseRequest request): void
President
+ +
President (String name)
processRequest (PurchaseRequest request): void
successor
SearchContext
abstract}
{ #successor: SearchContext
+ +
setSuccessor (SearchContext successor) search (String keyword) : void : void
JavaSearchContext + search (String keyword): void
UMLSearchContext + search (String keyword): void
Client
SQLSearchContext + search (String keyword): void
其中,Switch 充当调用者(发送者)角色,Command 是抽象命令类,LampCommand 和FanCommand 充当具体命令角色,Lamp 和Fan 充当接收者角色。

6.某软件公司欲开发一个基于Windows 平台的公告板系统。

系统提供一个主菜单(Menu),在主菜单中包含了一些菜单项(MenuItem),可以通过Menu 类的addMenuItem()方法增加菜单项。

菜单项的主要方法是click(),每一个菜单项包含一个抽象命令类,具体命令类包括OpenCommand(打开命令),CreateCommand(新建命令),EditCommand(编辑命令)等,命令类具有一个execute()方法,用于调用公告板系统界面类(BoardScreen)的open()、create()、edit()等方法。

现使用命令模式设计该系统,使得MenuItem 类与BoardScreen 类的耦合度降低,绘制类图并编程实现。

参考答案:
其中,BoardScreen 充当接收者角色,MenuItem 充当调用者角色,Command 充当抽象命令角色,OpenCommand 、CreateCommand 和 EditCommand 充当具体命令角色。

实验 4
1. 某实时在线股票软件需要提供如下功能:当股票购买者所购买的某支股票价格变化幅度达到 5%时,系统将自动发送通知(包括新价格)给购买该股票的所有股民。

试使用观察者模式设计并实现该系统,要求绘制相应的类图并编程模拟实现。

参考答案:
BoardScreen - menu: Menu + + + + +
BoardScreen () display () open () create () edit () : void : void : void : void
Menu
+ itemList: ArrayList
addMenuItem (MenuItem item): void
+ MenuItem
- - name command : String
: Command + + + + + +
MenuItem (String name) getName () setName (String name) getCommand () setCommand (Command command) click () : String : void : Command : void void
: Command + execute (): void
OpenCommand
- screen: BoardScreen
+ +
OpenCommand (BoardScreen screen) : execute () void CreateCommand
- screen: BoardScreen
+ +
CreateCommand (BoardScreen screen) execute () : void
EditCommand
- screen: BoardScreen
+ +
EditCommand (BoardScreen screen) void
execute () : investors ConcreteInvestor name: String - + +
ConcreteInvestor (String name) void
response (Stock stock) : Investor
+ response (Stock stock): void Stock
- - - investors stockName price : ArrayList : String
double : + + + + + + + +
Stock (String stockName, double price) attach (Investor investor) detach (Investor investor) setStockName (String stockName) getStockName () setPrice (double price) getPrice () notifyInvestor () : void : void : void : String : void : double : void
2.某公司欲开发一套机房监控系统,如果机房达到某一指定温度,温度传感器
(Thermosensor)将自动传递信号给各种响应设备,例如警示灯(CautionLight)将闪烁(flicker())、
报警器(Annunciator)将发出警报(alarm())、安全逃生门(SecurityDoor)将自动开启(open())、隔热门(InsulatedDoor)将自动关闭(close())等,每一种响应设备的行为由专门的程序来控制。

为了将来能够方便地引入新类型的响应设备,采用观察者模式和适配器模式设计并模拟实现该系统。

参考答案:
3.某软件公司为某电影院开发了一套影院售票系统,在该系统中需要为不同类型的用户提供不同的电影票(MovieTicket)打折(Discount)方式,具体打折方案如下:
(1)学生凭学生证可享受票价8 折优惠;
(2)年龄在10 周岁及以下的儿童可享受每张票减免10 元的优惠(原始票价需大于等

20 元);
(3)影院VIP 用户除享受票价半价优惠外还可进行积分,积分累计到一定额度可换取电影院赠送的奖品。

该系统在将来可能还要根据需要引入新的打折方式。

试使用策略模式设计并编程模拟实现该影院售票系统。

参考答案:
其中,MovieTicket 充当环境类角色,Discount 充当抽象策略角色,StudentDiscount 、 ChildrenDiscount 和 VIPDiscount 充当具体策略角色。

MovieTicket 充当环境类角色,Discount
充当抽象策略角色,StudentDiscount 、ChildrenDiscount 和 VIPDiscount 充当具体策略角色。

(4) 某软件公司欲开发一款飞机模拟系统,该系统主要模拟不同种类飞机的飞行特征与起飞特征,需要模拟的飞机种类及其特征如表 1 所示:
表 1 飞机种类及特征一览表
飞机种类
起飞特征
飞行特征
直升机(Helicopter) 垂直起飞(VerticalTakeOff) 亚音速飞行(SubSonicFly)
客机(AirPlane) 长距离起飞(LongDistanceTakeOff) 亚音速飞行(SubSonicFly) 歼击机(Fighter) 长距离起飞(LongDistanceTakeOff) 超音速飞行(SuperSonicFly)
鹞式战斗机(Harrier) 垂直起飞(VerticalTakeOff)
超音速飞行(SuperSonicFly)
为将来能够模拟更多种类的飞机,试采用策略模式设计并模拟实现该飞机模拟系统。

参考答案:
StudentDiscount
calculate (double price): double
+ Discount
+ calculate (double price): double
MovieTicket
- - price discount double : : Discount + + +
setPrice (double price) setDiscount (Discount discount) getPrice () : void : void : double
ChildrenDiscount
+ calculate (double price): double
VIPDiscount
+ calculate (double price): double
AirCraft
{ a bstract}
# # flyBehavior takeOffBehavior : FlyBehavior : TakeOffBehavior + +
fly () takeOff ()
FlyBehavior + fly ()
TakeOffBehavior + takeOff ()
SubSonicFly ()
+ fly SuperSonicFly ()
fly + VerticalTakeOff + () takeOff LongDistanceTakeOff + takeOff ()
Helicopter
AirPlane
Fighter
Harrier。

相关文档
最新文档