《设计模式》刘伟 实验_第1页
《设计模式》刘伟 实验_第2页
《设计模式》刘伟 实验_第3页
《设计模式》刘伟 实验_第4页
《设计模式》刘伟 实验_第5页
已阅读5页,还剩17页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、设计模式刘伟 实验参考答案 实验 1 1在某图形库 api 中提供了多种矢量图模板,用户可以基于这些矢量图创建不同的显示图形,图形库设计人员设计的初始类图如下所示: 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

2、 () void: void: void: void: voidclient 在该图形库中,每个图形类(如 circle、triangle 等)的 init()方法用于初始化所创建的图形, setcolor()方法用于给图形设置边框颜色,fill()方法用于给图形设置填充颜色,setsize() 方法用于设置图形的大小,display()方法用于显示图形。 客户类(client)在使用该图形库时发现存在如下问题: 由于在创建窗口时每次只需要使用图形库中的一种图形,因此在更换图形时需要修改客户类源代码; 在图形库中增加并使用新的图形时需要修改客户类源代码; 客户类在每次使用图形对象之前需要先创建

3、图形对象,有些图形的创建过程较为复杂,导致客户类代码冗长且难以维护。 现需要根据面向对象设计原则对该系统进行重构,要求如下: 隔离图形的创建和使用,将图形的创建过程封装在专门的类中,客户类在使用图形时无须直接创建图形对象,甚至不需要关心具体图形类类名; 客户类能够方便地更换图形或使用新增图形,无须针对具体图形类编程,符合开闭原则。 绘制重构之后的类图并说明在重构过程中所运用的面向对象设计原则。 参考答案: 2使用简单工厂模式设计一个可以创建不同几何形状(shape),如圆形(circle)、矩形(rectangle)和三角形(triangle)等的绘图工具类,每个几何图形均具有绘制draw()

4、和擦除erase()两个方法,要求在绘制不支持的几何图形时,抛出一个 unsupportedshapeexception 异常,绘制类图并编程模拟实现。 参考答案: shapefactorycreateshape (string type): shape+circle+draw ()erase (): void: voidtriangle+draw ()erase (): void void:shape+draw ()erase (): void: voidrectangle+draw ()erase (): void: voidunsupportedshapeexception(+unsup

5、portedshapeexception string message) 3. 现需要设计一个程序来读取多种不同类型的图片格式,针对每一种图片格式都设计一个图片读取器(imagereader),如 gif 图片读取器(gifreader)用于读取 gif 格式的图片、jpg 图片读取器(jpgreader)用于读取 jpg 格式的图片。图片读取器对象通过图片读取器工厂 imagereaderfactory 来创建,imagereaderfactory 是一个抽象类,用于定义创建图片读取器的工厂方法,其子类 gifreaderfactory 和 jpgreaderfactory 用于创建具体的图

6、片读取器对象。试使用工厂方法模式设计该程序,绘制类图并编程模拟实现。需充分考虑系统的灵活性和可扩展性。 参考答案: gifreaderfactorycreateimagereader (): imagereader+imagereaderfactorycreateimagereader (): imagereader+gifreader+readimage (): voidimagereader+readimage (): voidjpgreaderfactory+createimagereader (): imagereaderjpgreader+readimage (): void 4.

7、某软件公司欲开发一套界面皮肤库,可以对桌面软件进行界面美化。不同的皮肤将提供视觉效果不同的按钮、文本框、组合框等界面元素,其结构如下图所示: 该皮肤库需要具备良好的灵活性和可扩展性,用户可以自由选择不同的皮肤,开发人员可以在不修改既有代码的基础上增加新的皮肤。试使用抽象工厂模式设计该皮肤库,绘制类图并编程模拟实现。 参考答案: 5. 使用单例模式的思想实现多例模式,确保系统中某个类的对象只能存在有限个,例如两个或三个,设计并编写代码实现一个多例类。参考答案: multiton- array : multiton- multiton ()+ getinstance () : multiton+

8、random (): int多例模式(multiton pattern)是单例模式的一种扩展形式,多例类可以有多个实例,而且必须自行创建和管理实例,并向外界提供自己的实例,可以通过静态集合对象来存储这些实例。多例类 multiton 的代码如下所示: import java.util.*; public class multiton /定义一个数组用于存储四个实例 private static multiton array = new multiton(), new multiton(), new multiton(), new multiton(); /私有构造函数 private mult

9、iton() /静态工厂方法,随机返回数组中的一个实例 public static multiton getinstance() return arrayrandom(); /随机生成一个整数作为数组下标 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 m

10、1,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 来实现),要求在主窗体中某个内部子

11、窗体只能实例化一次,即只能弹出一个相同的子窗体,如下图所示,编程实现该功能。 (注:用 c#或 c+实现类似功能也可以)参考答案: subframe-frame: subframe-+subframe ()getframe (): subframemyiflistenermainclass-buttondesktoppaneiframe: jbutton: jdesktoppane: subframe+()mainclass btlistener subframe 类充当单例类,在其中定义了静态工厂方法 getframe()。 代码如下所示: import java.awt.*; import

12、 java.awt.event.*; import javax.swing.*; import javax.swing.event.*; /子窗口:单例类 class subframe extends jinternalframe private static subframe frame;/静态实例 /私有构造函数 private subframe() super(子窗体, true, true, true, false); this.setlocation(20,20); /设置内部窗体位置 this.setsize(200,200); /设置内部窗体大小 this.addinternal

13、framelistener(new myiflistener();/监听窗体事件 this.setvisible(true); /工厂方法,返回窗体实例 public static subframe getframe() /如果窗体对象为空,则创建窗体,否则直接返回已有窗体 if(frame=null) frame=new subframe(); return frame; /事件监听器 class myiflistener extends internalframeadapter /子窗体关闭时,将窗体对象设为 null public void internalframeclosing(in

14、ternalframeevent e) if(frame!=null) frame=null; /客户端测试类 class mainclass extends jframe private jbutton button; private jdesktoppane desktoppane; private subframe iframe=null; public mainclass() super(主窗体); container c=this.getcontentpane(); c.setlayout(new borderlayout(); button=new jbutton(点击创建一个内部

15、窗体); button.addactionlistener(new btlistener(); c.add(button, borderlayout.south); desktoppane = new jdesktoppane(); /创建 desktoppane c.add(desktoppane); this.setdefaultcloseoperation(jframe.exit_on_close); this.setlocationrelativeto(null); this.setsize(400,400); this.show(); /事件监听器 class btlistener

16、implements actionlistener public void actionperformed(actionevent e) if(iframe!=null) desktoppane.remove(iframe); iframe=subframe.getframe(); desktoppane.add(iframe); public static void main(string args) new mainclass(); subframe 类是 jinternalframe 类的子类,在 subframe 类中定义了一个静态的 subframe 类型的实例变量,在静态工厂方法

17、getframe()中创建了 subframe 对象并将其返回。在 mainclass 类中使用了该单例类,确保子窗口在当前应用程序中只有唯一一个实例,即只能弹出一个子窗口。 实验 2 1. 现有一个接口 dataoperation 定义了排序方法 sort(int) 和查找方法 search(int, int),已知类 quicksort 的 quicksort(int)方法实现了快速排序算法,类 binarysearch 的 binarysearch(int, int)方法实现了二分查找算法。试使用适配器模式设计一个系统,在不修改源代码的情况下将类 quicksort 和类 binarys

18、earch 的方法适配到 dataoperation 接口中。绘制类图并编程实现。(要求实现快速排序和二分查找,使用对象适配器实现)参考答案: operationadapter-sortobjsearchobj quicksort: binarysearch+operationadapter (quicksort sortobj, binarysearch searchobj)sort (int array)search (int array, int key): int: intdataoperation+sort (int array)search (int array, int key)

19、 int: intquicksort+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): intclient 2. windows media player 和 realplayer 是两种常用的媒体播放器,它们的 api 结构和调用方法存在区别。现在你的应用程序需要支持这两种播放器 api,而

20、且在将来可能还需要支持新的媒体播放器,请问如何设计该应用程序?绘制类图并编程模拟实现。 参考答案: 可使用适配器模式和抽象工厂模式,参考类图如下所示: mediaplayerwindowmainwindowmediaplayerfactory+createmainwindow ()createplayerlist () mainwindow: playerlist:playerfactory+createmainwindow ()createplayerlist (): mainwindow: playerlistclientclassrealplayerfactory+createmainw

21、indow ()createplayerlist () mainwindow: playerlistrealplayerwindowmediaplayerlistplayerlistrealplayerlistmediaplayerapirealplayerapi 在该类图中,为两种不同的播放器提供了两个具体工厂类 mediaplayerfactory 和realplayerfactory,其中 mediaplayerfactory 作为 windows media player 播放器工厂,可以创建 windows media player 的主窗口(mediaplayerwindow)和播

22、放列表(mediaplayerlist)(为了简化类图,只列出主窗口和播放列表这两个播放器组成元素,实际情况下包含更多组成元素); realplayerfactory 作为 realplayer 播放器工厂,创建 realplayer 的主窗口 (realplayerwindow)和播放列表(realplayerlist),此时可以使用抽象工厂模式,客户端针对抽象工厂 playerfactory 编程,如果增加新的播放器,只需增加一个新的具体工厂来生产新产品族中的产品即可。由于需要调用现有 api 中的方法,因此还需要使用适配器模式,在具体产品类如 mediaplayerwindow 和 me

23、diaplayerlist 调用 windows media player api 中的方法,在 realplayerwindow 和 realplayerlist 中调用 realplayer api 中的方法,实现对 api 中方法的适配,此时具体产品如 mediaplayerwindow、realplayerwindow 等充当适配器,而已有的 api 如 mediaplayerapi 和 realplayerapi 是需要适配的适配者。 3. 使用组合模式设计一个杀毒软件(antivirus)的框架,该软件既可以对某个文件夹(folder)杀毒,也可以对某个指定的文件(file)进行杀

24、毒,文件种类包括文本文件 textfile、图片文件 imagefile、视频文件 videofile。绘制类图并编程模拟实现。 参考答案: filelistabstractfileabstract +add (abstractfile file)remove (abstractfile file)getchild (int i)killvirus () void: void abstractfile: voidimagefilename: string-+imagefile (string name)add (abstractfile file)remove (abstractfile fi

25、le)getchild (int i)killvirus () void: void abstractfile: void:folder-filelistname arraylist: string:+folder (string name)add (abstractfile file)remove (abstractfile file)getchild (int i)killvirus (): void void: abstractfile: voidtextfile-name: string+textfile (string name)add (abstractfile file)remo

26、ve (abstractfile file)getchild (int i)killvirus () void: void abstractfile: void:videofilename: string-+videofile (string name)add (abstractfile file)remove (abstractfile file)getchild (int i)killvirus () void: void: abstractfile void: 4. 某教育机构组织结构如下图所示: 北京总部教务办公室湖南分校行政办公室长沙教学点湘潭教学点教务办公室行政办公室教务办公室行政

27、办公室教务办公室行政办公室 在该教育机构的 oa 系统中可以给各级办公室下发公文,试采用组合模式设计该机构的组织结构,绘制相应的类图并编程模拟实现,在客户端代码中模拟下发公文。 参考答案: 参考类图如下所示: listunitabstract +handlearchives (): voidofficename: string-+office (string name)handlearchives (): voidinstitution-listname: arraylist: string+institution (string name)add (unit unit)handlearchi

28、ves (): void: void 本实例使用了安全组合模式,unit 充当抽象构件角色,office 充当叶子构件角色,institution 充当容器构件角色。本实例代码如下所示: abstract class unit public abstract void handlearchives(); class office extends unit private string name; public office(string name) = name; public void handlearchives() system.out.println(this.na

29、me + 处理公文!); class institution extends unit private arraylist list = new arraylist(); private string name; public institution(string name) = name; public void add(unit unit) list.add(unit); public void handlearchives() system.out.println( + 接收并下发公文:); for(object obj : list) (unit)

30、obj).handlearchives(); 在客户类中创建树形结构,代码如下所示: class client public static void main(string args) institution bjheadquarters,hnsubschool,csteachingpost,xtteachingpost; unit toffice1,toffice2,toffice3,toffice4,aoffice1,aoffice2,aoffice3,aoffice4; bjheadquarters = new institution(北京总部); hnsubschool = new i

31、nstitution(湖南分校); csteachingpost = new institution(长沙教学点); xtteachingpost = new institution(湘潭教学点); toffice1 = new office(北京教务办公室); toffice2 = new office(湖南教务办公室); toffice3 = new office(长沙教务办公室); toffice4 = new office(湘潭教务办公室); aoffice1 = new office(北京行政办公室); aoffice2 = new office(湖南行政办公室); aoffice3

32、 = new office(长沙行政办公室); aoffice4 = new office(湘潭行政办公室); csteachingpost.add(toffice3); csteachingpost.add(aoffice3); xtteachingpost.add(toffice4); xtteachingpost.add(aoffice4); hnsubschool.add(csteachingpost); hnsubschool.add(xtteachingpost); hnsubschool.add(toffice2); hnsubschool.add(aoffice2); bjhe

33、adquarters.add(hnsubschool); bjheadquarters.add(toffice1); bjheadquarters.add(aoffice1); bjheadquarters.handlearchives(); 注:本题也可以将员工(employee)作为叶子构件,将 unit 作为容器构件。 5. 某软件公司为新开发的智能手机控制与管理软件提供了一键备份功能,通过该功能可以将原本存储在手机中的通信录、短信、照片、歌曲等资料一次性全部拷贝到移动存储介质(例如 mmc 卡或 sd 卡)中。在实现过程中需要与多个已有的类进行交互,例如通讯录管理类、短信管理类等,为了

34、降低系统的耦合度,试使用外观模式来设计并编程模拟实现该一键备份功能。 参考答案: 参考类图如下所示: onekeybackup-cmmmfm contactmanager: messagemanager: filemanager+click (): voidcontactmanager+backup (): voidmessagemanager+backup (): voidfilemanager+backup (): void 其中,onekeybackup 充当外观角色,contactmanager、messagemanager 和 filemanager 充当子系统角色。 6. 某信息系

35、统需要提供一个数据处理和报表显示模块,该模块可以读取不同类型的文件中的数据并将数据转换成 xml 格式,然后对数据进行统计分析,最后以报表方式来显示数据。由于该过程需要涉及到多个类,试使用外观模式设计该数据处理和报表显示模块。考虑到有些文件本身已经是 xml 格式,无须进行格式转换,为了让系统具有更好的扩展性,在系统设计中可以引入抽象外观类。 参考答案: abstractfacadeabstract +()execute xmlfacade+execute ()extendedfacade+execute ()fileoperation+read ()xmldataconvertor+conv

36、ert ()reportdisplay+display ()dataanalysis()+handle 实验 3 1. 在某应用软件中需要记录业务方法的调用日志,在不修改现有业务类的基础上为每一个类提供一个日志记录代理类,在代理类中输出日志,例如在业务方法 method()调用之前输出“方法 method()被调用,调用时间为 2014-11-5 10:10:10”,调用之后如果没有抛异常则输出“方法 method()调用成功”,否则输出“方法 method()调用失败”。在代理类中调用真实业务类的业务方法,使用代理模式设计该日志记录模块的结构,绘制类图并编程模拟实现。 参考答案: busin

37、essclassmethod (): void+abstractlog+method (): voidloggerproxy-business: businessclass+loggerproxy ()method (): voidclient 2. 某软件公司承接了某信息咨询公司的收费商务信息查询系统的开发任务,该系统的基本需求如下: (1) 在进行商务信息查询之前用户需要通过身份验证,只有合法用户才能够使用该查询系统; (2) 在进行商务信息查询时系统需要记录查询日志,以便根据查询次数收取查询费用。 该软件公司开发人员已完成了商务信息查询模块的开发任务,现希望能够以一种松耦合的方式向原有系

38、统增加身份验证和日志记录功能,客户端代码可以无区别地对待原始的商务信息查询模块和增加新功能之后的商务信息查询模块,而且可能在将来还要在该信息查询模块中增加一些新的功能。 试使用代理模式设计并编程模拟实现该收费商务信息查询系统。【提示:使用保护代理和智能引用代理】参考答案: proxysearcher-searchervalidatorlogger: realsearcher accessvalidator: logger:+dosearch ()validate ()log () string: boolean: void:searcher+dosearch (): stringrealsea

39、rcherdosearch (): string+accessvalidator+validate (): booleanlogger+log (): void 3. 某企业的 scm(supply chain management,供应链管理)系统中包含一个采购审批子系统。该企业的采购审批是分级进行的,即根据采购金额的不同由不同层次的主管人员来审批,主任可以审批 5 万元以下(不包括 5 万元)的采购单,副董事长可以审批 5 万元至 10 万元(不包括 10 万元)的采购单,董事长可以审批 10 万元至 50 万元(不包括 50 万元)的采购单,50 万元及以上的采购单就需要开董事会讨论决定

40、。如下图所示: 参考答案: successorapproverabstract #successorname: approver: string+approver (string name)setsuccessor (approver successor)processrequest (purchaserequest request): void: voiddirector+director (string name)processrequest (purchaserequest request): voidcongress+congress (string name)processreque

41、st (purchaserequest request): voidpurchaserequest-amountnumberpurpose: 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: stringv

42、icepresident+vicepresident (string name)processrequest (purchaserequest request): voidpresident+president (string name)processrequest (purchaserequest request): void 4. 某公司欲开发一个软件系统的在线文档帮助系统,用户可以在任何一个查询上下文中输入查询关键字,如果当前查询环境下没有相关内容,则系统会将查询按照一定的顺序转发给其他查询环境。基于上述需求,试采用职责链模式对该系统进行设计。 参考答案: successorsearch

43、contextabstract #successor: searchcontext+setsuccessor (searchcontext successor)search (string keyword): void: voidjavasearchcontext+search (string keyword): voidumlsearchcontext+search (string keyword): voidclientsqlsearchcontext+search (string keyword): void 5. 房间中的开关就是命令模式的一个实例,现用命令模式来模拟开关的功能,可控制

44、对象包括电灯和电风扇,绘制相应的类图并编程模拟实现。 参考答案: 参考类图如下所示: lampfanswitch+on ()off () void: void:command+executeon ()executeoff (): void: voidlampcommand-lamp: lamp+executeon ()executeoff (): void: voidlamp+lighten ()quench (): void: voidfancommand-fan: fan+executeon ()executeoff (): void: voidfan+run ()stop (): voi

45、d: void 其中,switch 充当调用者(发送者)角色,command 是抽象命令类,lampcommand 和 fancommand 充当具体命令角色,lamp 和 fan 充当接收者角色。 6. 某软件公司欲开发一个基于 windows 平台的公告板系统。系统提供一个主菜单(menu),在主菜单中包含了一些菜单项(menuitem),可以通过 menu 类的 addmenuitem()方法增加菜单项。菜单项的主要方法是 click(),每一个菜单项包含一个抽象命令类,具体命令类包括 opencommand(打开命令),createcommand(新建命令),editcommand(编

46、辑命令)等,命令类具有一个 execute()方法,用于调用公告板系统界面类(boardscreen)的 open()、create()、 edit()等方法。现使用命令模式设计该系统,使得 menuitem 类与 boardscreen 类的耦合度降低,绘制类图并编程实现。 参考答案: boardscreen-menu: menu+boardscreen ()display ()open ()create ()edit (): void: void: void: voidmenu+itemlist: arraylistaddmenuitem (menuitem item): void+men

47、uitem-namecommand: string: command+menuitem (string name)getname ()setname (string name)getcommand ()setcommand (command command)click (): string: void: command: void void:command+execute (): voidopencommand-screen: boardscreen+opencommand (boardscreen screen):execute () voidcreatecommand-screen: bo

48、ardscreen+createcommand (boardscreen screen)execute (): voideditcommand-screen: boardscreen+editcommand (boardscreen screen) voidexecute (): 其中,boardscreen 充当接收者角色,menuitem 充当调用者角色,command 充当抽象命令角色,opencommand、createcommand 和 editcommand 充当具体命令角色。 实验 4 1. 某实时在线股票软件需要提供如下功能:当股票购买者所购买的某支股票价格变化幅度达到 5%时

49、,系统将自动发送通知(包括新价格)给购买该股票的所有股民。试使用观察者模式设计并实现该系统,要求绘制相应的类图并编程模拟实现。 参考答案: investorsconcreteinvestorname: string-+concreteinvestor (string name) voidresponse (stock stock):investor+response (stock stock): voidstock-investorsstocknameprice: arraylist: string double:+stock (string stockname, double price)attach (investor investor)detach (investor investor)setstockname (string stockname)getstockname ()set

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论