设计模式课程设计.docx
《设计模式课程设计.docx》由会员分享,可在线阅读,更多相关《设计模式课程设计.docx(16页珍藏版)》请在冰点文库上搜索。
设计模式课程设计
设计模式课程设计
题目:
画图程序
学院:
信息科学与技术学院
专业:
软件工程
学号:
20092384
姓名:
陈志
1.需求分析
该系统是一个画图程序,我们要用设计模式的思想来设计系统结构,然后实现基本图形的绘制功能。
1.1设计模式要求
至少在其中运用6种模式,其中涉及到的模式有装饰模式、策略模式、桥梁模式三种。
1.2画图基本要求
能实现基本图形的绘制功能
1.3画图高级要求
实现图形的操作(如选取、移动、放大、缩小、改变颜色、改变线形等)和持久化(利用文件或利用数据库)。
2.系统设计
首先,画图程序可以实现绘制圆形、矩形和按钮,这里可以将圆形、矩形和按钮看作三个不同的类,那么我们可以采用抽象工厂的方式来创建它们。
对于画组合图,我们可以采用组合模式将二者结合起来。
而对于图形颜色或者粗细的改变,我们可以使用外观模式。
然后,我们可以使用原型模式来实现对于最后一个图形的复制。
在系统中可以使用代理模式来实现显示图片。
下面是对需要用到的设计模式进行的分析。
矚慫润厲钐瘗睞枥庑赖。
2.1使用设计模式
2.1.1桥梁模式
桥梁模式,结构型模式一种.设计程序过程中,会经常使用到抽象类或者接口来完成抽象的过程。
继承或实现的类通过不同的实现方式来完成抽象类或接口的变化,也就是实现过程的变化,但可能会有这样的情况,抽象过程同样需要进行变化,也就是抽象类或者接口需要变化,这样就会造成原有的继承或实现关系复杂,关系混乱.桥梁模式利用将抽象层和实现层进行解耦,使两者不再像继承或实现这样的较强的关系,从而使抽象和实现层更加独立的完成变化的过程.使系统更加清晰。
聞創沟燴鐺險爱氇谴净。
桥梁模式主要由抽象类、修正抽象类、实现类以及具体实现类组成.
抽象类,制定接口,同时给出一个实现化的引用。
修正抽象类,扩展抽象类,修正或改变抽象类中指定的接口。
实现类,提供实现化角色的接口,但不进行具体实现过程,该接口不一定给出与抽象类相同的接口,只是提供实现的方式。
残骛楼諍锩瀨濟溆塹籟。
具体实现类,完成实现类中定义的实现接口的具体实现过程。
具体代码如下:
packageBridgePattern。
importjava.awt.Color。
importjava.awt.Graphics。
importjava.util.Random。
importcn.ming.Main.circle。
publicclassCpicextendsPic
{
publicCpic(Graphicsg){
super(g)。
}
publicvoiddrawpic(Graphicsg){
g.setColor(Color.RED)。
circlec1=newcircle()。
Randomran2=newRandom()。
inta=ran2.nextInt(150)+10。
intb=ran2.nextInt(350)+200。
intc=ran2.nextInt(280)+140。
c1.settings(a,b,c)。
g.fillOval(b-a/2,c-a/2,a,a)。
g.setColor(Color.BLUE)。
g.fillOval(50+b-a/2,c-a/2-50,a,a)。
g.setColor(Color.GREEN)。
g.fillOval(100+b-a/2,c-a/2,a,a)。
}
}
packageBridgePattern。
importjava.awt.Graphics。
publicabstractclassPic
{
publicGraphicsg。
Pic(Graphicsg){
this.g=g。
}
publicabstractvoiddrawpic(Graphicsg)。
}
packageBridgePattern。
importjava.awt.Color。
importjava.awt.Graphics。
importjava.util.Random。
importcn.ming.Main.circle。
publicclassRpicextendsPic
{
publicRpic(Graphicsg){
super(g)。
}
publicvoiddrawpic(Graphicsg){
g.setColor(Color.RED)。
circlec2=newcircle()。
Randomran2=newRandom()。
inta=ran2.nextInt(150)+10。
intb=ran2.nextInt(350)+100。
intc=ran2.nextInt(150)+100。
c2.settings(a,b,c)。
g.fillOval(b-a/2,c-a/2,a,a)。
g.setColor(Color.BLUE)。
g.fillOval(b-3*a/8,c-3*a/8,3*a/4,3*a/4)。
g.setColor(Color.WHITE)。
g.fillOval(b-a/4,c-a/4,a/2,a/2)。
g.setColor(Color.GREEN)。
g.fillOval(b-a/8,c-a/8,a/4,a/4)。
}
}
运行结果:
2.1.2装饰模式
JAVA23种设计模式之一,英文叫DecoratorPattern,又叫装饰者模式。
装饰模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。
它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
酽锕极額閉镇桧猪訣锥。
装饰模式的特点。
(1)装饰对象和真实对象有相同的接口。
这样客户端对象就可以和真实对象相同的方式和装饰对象交互。
(2)装饰对象包含一个真实对象的引用(reference)
(3)装饰对象接受所有来自客户端的请求。
它把这些请求转发给真实的对象。
(4)装饰对象可以在转发这些请求以前或以后增加一些附加功能。
这样就确保了在运行时,不用修改给定对象的结构就可以在外部增加附加的功能。
在面向对象的设计中,通常是通过继承来实现对给定类的功能扩展。
彈贸摄尔霁毙攬砖卤庑。
具体代码如下:
packageDecoratorPattern。
importjava.awt.Graphics。
importcn.ming.Main.triangles。
publicclassDecoTrextendstriangles
{
publictrianglest。
privateGraphicsg。
publicDecoTr(){
t=newtriangles()。
}
publicstaticvoidfilltr(Graphicsg,trianglest){
if(t!
=null)
t.filltr(g,t)。
}
}
packageDecoratorPattern。
importjava.awt.Color。
importjava.awt.Graphics。
importcn.ming.Main.Triangle。
publicclassDecoTr1extendsDecoTr
{
publicstaticvoidfilltr(Graphicsg,Trianglet){
g.setColor(Color.GREEN)。
g.fillOval(t.x-25,t.y-25,50,50)。
}
}
packageDecoratorPattern。
importjava.awt.Color。
importjava.awt.Graphics。
importcn.ming.Main.Triangle。
publicclassDecoTr2extendsDecoTr
{
publicstaticvoidfilltr(Graphicsg,Trianglet){
g.setColor(Color.RED)。
g.fillOval(t.x+t.w-25,t.y-25,50,50)。
}
}
运行结果:
2.1.3策略模式
策略模式,又叫算法簇模式,就是定义了不同的算法族,并且之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
謀荞抟箧飆鐸怼类蒋薔。
设计原则是把一个类中经常改变或者将来可能改变的部分提取出来,作为一个接口(c++z中可以用虚类),然后在类中包含这个对象的实例,这样类的实例在运行时就可以随意调用实现了这个接口的类的行为。
下面是一个例子。
厦礴恳蹒骈時盡继價骚。
策略模式属于对象行为型模式,主要针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。
策略模式使得算法可以在不影响到客户端的情况下发生变化。
通常,策略模式适用于当一个应用程序需要实现一种特定的服务或者功能,而且该程序有多种实现方式时使用。
茕桢广鳓鯡选块网羈泪。
具体代码实现如下:
packageStrategyPattern。
importjava.awt.Graphics。
importjava.awt.Point。
publicclasspolicy
{
strategys。
publicpolicy(strategys){
this.s=s。
}
publicvoidchoosepolicy(Graphicsg,Pointp1,Pointp2,Pointp3){鹅娅尽損鹌惨歷茏鴛賴。
s.drawing(g,p1,p2,p3)。
}
}
packageStrategyPattern。
importjava.awt.Graphics。
importjava.awt.Point。
publicabstractclassstrategy
{
publicabstractvoiddrawing(Graphicsg,Pointp1,Pointp2,Pointp3)。
籟丛妈羥为贍偾蛏练淨。
}
packageStrategyPattern。
importjava.awt.Color。
importjava.awt.Graphics。
importjava.awt.Point。
publicclassstrategyAextendsstrategy
{
publicPointp1,p2,p3。
publicdoublearea,p。
publicdoubledistenceOfPoints(Pointp1,Pointp2){預頌圣鉉儐歲龈讶骅籴。
returnMath.sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y))。
渗釤呛俨匀谔鱉调硯錦。
}
publicPointgetCircumcenter(Pointp1,Pointp2,Pointp3){铙誅卧泻噦圣骋贶頂廡。
doubledis12=distenceOfPoints(p1,p2)。
doubledis23=distenceOfPoints(p2,p3)。
doubledis31=distenceOfPoints(p3,p1)。
p=dis12+dis23+dis31。
doublepp=p/2。
area=Math.sqrt(pp*(pp-dis12)*(pp-dis23)*(pp-dis31))。
擁締凤袜备訊顎轮烂蔷。
doublex=(p1.x*dis23+p2.x*dis31+p3.x*dis12)/p。
贓熱俣阃歲匱阊邺镓騷。
doubley=(p1.y*dis23+p2.y*dis31+p3.y*dis12)/p。
坛摶乡囂忏蒌鍥铃氈淚。
returnnewPoint((int)x,(int)y)。
}
publicvoiddrawing(Graphicsg,Pointp1,Pointp2,Pointp3){//Pointsp1,Pointsp2,Pointsp3蜡變黲癟報伥铉锚鈰赘。
g.drawLine(p1.x,p1.y,p2.x,p2.y)。
g.drawLine(p2.x,p2.y,p3.x,p3.y)。
g.drawLine(p3.x,p3.y,p1.x,p1.y)。
Pointcenter=getCircumcenter(p1,p2,p3)。
doubleradius=(2*area)/p。
intx=(int)(center.x-radius)。
inty=(int)(center.y-radius)。
intwidth=(int)(radius*2)。
g.setColor(Color.BLUE)。
g.fillOval(x,y,width,width)。
}
}
packageStrategyPattern。
importjava.awt.Color。
importjava.awt.Graphics。
importjava.awt.Point。
publicclassstrategyBextendsstrategy
{
publicPointp1,p2,p3。
publicPointgetCircumcenter(Pointp1,Pointp2,Pointp3){買鲷鴯譖昙膚遙闫撷凄。
doublea=2*(p2.x-p1.x)。
doubleb=2*(p2.y-p1.y)。
doubledp1=p1.x*p1.x+p1.y*p1.y。
doubledp2=p2.x*p2.x+p2.y*p2.y。
doubledp3=p3.x*p3.x+p3.y*p3.y。
doublec=dp2-dp1。
doubled=2*(p3.x-p2.x)。
doublee=2*(p3.y-p2.y)。
doublef=dp3-dp2。
doublex=(b*f-e*c)/(b*d-e*a)。
doubley=(d*c-a*f)/(b*d-e*a)。
returnnewPoint((int)x,(int)y)。
}
publicvoiddrawing(Graphicsg,Pointp1,Pointp2,Pointp3){綾镝鯛駕櫬鹕踪韦辚糴。
g.drawLine(p1.x,p1.y,p2.x,p2.y)。
g.drawLine(p2.x,p2.y,p3.x,p3.y)。
g.drawLine(p3.x,p3.y,p1.x,p1.y)。
Pointcenter=getCircumcenter(p1,p2,p3)。
doubleradius=center.distance(p1)。
intx=(int)(center.x-radius)。
inty=(int)(center.y-radius)。
intwidth=(int)(radius*2)。
g.setColor(Color.red)。
g.drawOval(x,y,width,width)。
}
}
运行结果:
2.2画图功能分析
2.2.1画一个图形
当选定画一个图形后,由外观模式确定画图的类型,并且得到一个具体的圆形类、矩形类或按钮类的对象。
由鼠标按下的点确定圆形对象的圆心或者矩形和按钮对象的起始点,鼠标起来的点和按下点的关系确定圆形对象的半径或者矩形和按钮对象的长度和宽度。
然后将该对象的所有信息包括上面所述的信息和图形类型、画笔颜色和画笔宽度设置好了后,加入享元类中。
驅踬髏彦浃绥譎饴憂锦。
2.2.2画组合图
2.2.3选中图形
关于选中图形,采用遍历享元的方式,考虑到一般情况先前一个图的区域会被后面所画的图区域覆盖,那么我们从享元的后面开始遍历,当鼠标按下的点位于某个对象区域之中时,改变其颜色,并且提供移动其位置的功能。
当选中一个图形时,可以使用加装饰或者减装饰的功能,还可以提供放大和缩小的功能。
猫虿驢绘燈鮒诛髅貺庑。
当选择了选取功能时,就不能画图了,当我们选择“取消选取”后,取消了关于选取图形的操作,又可以画图了。
2.2.4加、减装饰
首先,你需要确定装饰的图形(对象)是哪个,需要选取那个图形。
当选好需要对那个图形后,创建装饰类的对象,然后给选定的对象加或者减装饰。
在该系统中,加、减装饰是对于画笔大小的操作,如果是加装饰那么就一个增加画笔的大小,否则减小画笔的大小到最小就不能减小了。
锹籁饗迳琐筆襖鸥娅薔。
2.2.5复制最后shape
复制最后一个图形我们可以采用原型模式。
在使用原型模式的时候要注意使用的是深拷贝,如果是浅拷贝,那么当将新的复制后的对象加入到享元后,其实是一个对象的两个副本,就不会显示出使用原型模式的特点。
当然,我们需要依据类型来赋值返回具体的图形。
構氽頑黉碩饨荠龈话骛。
3.心得体会
设计模式(Designpattern):
是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。
使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。
輒峄陽檉簖疖網儂號泶。
设计模式的种类很多,包括分布式编程模式、用户界面模式、数据模型模式三大类。
目前流行的面向对象设计模式,仅1995年“gangoffour”描述的就有二十多种,称之为GoF模式;与GoF模式相对应的是通用责任分配软件系列模式GRASP。
GRASP模式着重考虑设计类的原则及如何分配类的功能,而GoF模式则着重考虑设计的实现、类的交互及软件质量。
可以说,GoF模式就是符合GRASP模式要求的面向对象设计模式。
尧侧閆繭絳闕绚勵蜆贅。
设计模式的作用:
(1)重用设计,它比简单的重用代码更有意义;
(2)为设计提供共同的词汇,每个模式名就是一个设计词汇,其概念使得程序员间的交流更加方便;(3)在开发文档中采用设计模式词汇可以让其他人更任意理解你的想法,理解为什么你会这么做,你都做了些什么。
编写开发文档也更加任意;(4)应用设计模式可以让重构系统变得容易,可确保开发正确的代码,并降低在设计或实现中出错误的可能性;(5)可以节省大量时间。
识饒鎂錕缢灩筧嚌俨淒。