实验2 结构模式分析与应用 150364 陆榆嘉文档格式.docx
《实验2 结构模式分析与应用 150364 陆榆嘉文档格式.docx》由会员分享,可在线阅读,更多相关《实验2 结构模式分析与应用 150364 陆榆嘉文档格式.docx(12页珍藏版)》请在冰点文库上搜索。
4
实验时间:
2016年4月29日
实验报告提交时间:
2016年5月14日
一、实验目的与要求:
1.模式分析
对GoF23个设计模式中的结构型设计模式的UML图形表示,进行结构分析,发现与总结出反复出现的UML图形结构。
2.程序分析与应用
以Junit为例,要求实验者分析与欣赏其中与结构型设计模式中相关的部分。
要求实验者给出一个相关问题的结构型设计模式解决方案。
3.提交要求
(1)请提交电子版实验报告
(2)实验报告写作要求
实验报告样式应符合深圳大学学生实验报告要求&
&
源代码作为实验报告附件上传&
实验报告正文请不要粘贴源代码+实验指南,请介绍自己做的工作,包括操作是怎样进行的、程序是如何设计的,输出结果的详细解释与分析&
实验结论只需谈“实验过程中发现了什么问题,是否解决,解决思路是什么”,除此以外,请不要写其它内容在实验结论中.
(4)本实验完成人数:
1人
二、实验环境与内容
实验环境
UML工具、编程工具
实验内容
请回答带Q标记的问题。
以下为GoF23个设计模式的快速游览:
图1.GoF(GangofFour)设计模式的三大类:
创建型设计模式(CreationalPatterns)、结构型设计模式(StructuralPatterns)、行为设计模式(BehavioralPatterns)。
ObjectScope所标记的设计模式可用于运行时改变对象关系,ClassScope所标记的设计模式不能用于运行时,而只能用于编译时。
我们以结构型设计模式为主要研究内容,下面列举这7种结构型设计模式。
我们暂不分析它们的应用场景,而只是研究UML图的结构。
UML图的结构主要表现为:
继承(抽象)、关联、组合或聚合的三种关系,我们来看看这三种关系的各种可能的配合,可以变化出哪些可能的具体形式。
1.1关联后抽象
图2Adapter(适配器)设计模式。
采用的UML结构为:
关联后抽象。
将带关联的类ConcreteAdapter为接口Adapter。
其中可运行时改变的地方由“R”标记,即由ConcreteAdapter管理的adaptee成员变量可在运行时更改。
1.2关联的集合
图3Faç
ade(门面)设计模式。
关联集合
1.3组合接口
图4Bridge(桥)设计模式。
组合接口
1.4递归聚合接口
图5Decorator(装饰器)设计模式。
递归聚合接口
Q1:
下面的设计模式属于1.1~1.4中的哪一种,并给出说明。
图6Proxy(代理)设计模式
图7Composite(组合)设计模式
图8Flyweight(享元)设计模式
2.Junit案例研究
Q2:
试阅读Junit3源代码中的Test.java,TestCase.java,TestSuit.java、TestResult.java四个类的源代码(位于附件junit3.4.zip中的src.jar压缩文件中),给出这四个类的UML图结构。
我们先看一下在JUnit3中我们是怎样写一个单元测试的。
比如下面一个类:
publicclassAddOperation{
publicintadd(intx,inty){
returnx+y;
}
}
我们要测试add这个方法,我们写单元测试得这么写:
importjunit.framework.TestCase;
importstaticorg.junit.Assert.*;
publicclassAddOperationTestextendsTestCase{
publicvoidsetUp()throwsException{
publicvoidtearDown()throwsException{
publicvoidtestAdd(){
System.out.println(\"
add\"
);
intx=0;
inty=0;
AddOperationinstance=newAddOperation();
intexpResult=0;
intresult=instance.add(x,y);
assertEquals(expResult,result);
public
static
void
main(String[]
args)
{
TestCase
test=new
MoneyTest("
testAdd"
junit.textui.TestRunner.run(test);
Q3:
试从上述代码的junit.textui.TestRunner.run(test)处,跟踪代码的执行一直到junit的源代码:
TestRunner.java,BaseTestRunner.java,TestListener.java,TestSuiteLoader.java等,以说明Junit是如何使用Java反射机制:
通过框架类junit.textui.TestRunner调用任意客户类AddOperationTest的testAdd方法的。
(本题难度较高,请具备一定的心理素质和耐心)
3.递归聚合设计模式的应用
Q4:
试应用递归聚合设计模式实现一个样本应用,评价采用这种模式的优缺点。
三、实验结果及分析
与实验内容部分相对应。
图6属于关联后抽象,将带关联的类Proxy和RealSubject为接口Adapter。
其中由Proxy管理的ConcreteAdapter可运行时改变。
图7属于递归聚合接口,类Leaf和类Component共同继承接口Component,其中接口Component和类Component形成聚合关系。
图8属于关联集合和组合接口,Client、FlyweightFactory、ConcreteFlyweoght和UnsharedConcreteFlyweoght形成关联集合,而接口Flyweight和类FlyweightFactory、ConcreteFlyweoght、UnsharedConcreteFlyweoght形成组合接口。
Q2:
4个类的UML图如下所示,
Q3:
通过代码追踪,整个流程图为TestRunner→Testsuite→TestResult→testAdd()。
首先运行junit.textui.TestRunner.run(test),返回一个TestSuite对象,TestSuite将test构造为TestCase实例,然后调用TestResult.run(Test)方法,将测试出现异常或错误在TestResult中记录,如果是ThreadDeath就继续抛出异常,程序可能会终止,如果是其他错误和异常,程序将继续运行。
TestRunner通过调用TestSuite的run(TestResult)方法来开始测试,测试实例使用传递给它的TestResult实例来调用其run(Test)方法,并把自身作为参数传递给run方法,TestResult通过runBare()来回调它。
接下来就是测试testadd(),runBare()方法将调用setUp,testAdd,teardown方法,顺序执行,将结果通知给Listener,TestRunner受到错误或失败就会显示出来,最后TestResult调用endTest把结果通知给所有Listener。
假如我们需要编写一个图形库,图形有圆形、正方形等,并且实现图形的绘制和输出方法,如果我们为每一个图形编写一个类,每一个类里面有绘制(drawshape)和输出(display)两个方法,那么我们就需要编写多个类,并且每增加一个图形,就需要编写一个类,这明显不利于扩展功能,而且造成代码重复。
此时我们可以充分利用装饰模式,结合“合成复用原则”和“里氏代换原则”,将原来每一个图形类的drawshape方法置于一个独立的类中作为装饰类,在这个类中定义一个Shape类型的对象,通过调用Shape的display()方法来显示最基本的构件,同时再通过drawshape方法绘制图形。
该实现方法UML图如下,
优点:
(1)可以灵活、动态地扩展一个对象的功能;
(2)
可以对一个对象进行多次装饰,通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合,得到功能更为强大的对象。
(3)
具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,原有类库代码无须改变,符合“开闭原则”。
缺点:
(1)
使用装饰模式进行系统设计时将产生很多小对象,会消耗资源,在一定程序上影响程序的性能。
容错性差,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为繁琐。
四、实验总结与体会
这次实验相比上次难度明显增大,特别是Q3和Q4,但是难度大收获也大。
通过此次实验了解到了junit这个经典的单元测试框架,并且通过上网查资料以及花大部分时追踪源码,对其运行机理也得到认识。
通过Q4学习到了如果将课堂学习到的知识运用到实际生活中去,加大对知识点的巩固。
由于本人知识掌握不牢的原因,此次实验难免有些表述不当,还望老师谅解改正,本人将再接再厉争取完成接下来更好的实验。
六、成绩评定及评语
1.评语
2.成绩评定