填空题[问题3] 用SQL语言写出查询:查询年龄不在20~23岁(包括20岁和23岁)之间的学生的姓名,系别和年龄。
填空题
阅读以下说明和C代码,将应填入{{U}} (n) {{/U}}处的字句写在对应栏内。 [说明]
下面程序用来将打乱的单词还原为原来的次序,比如将rty还原为try。单词的原来次序存储于wordlist.txt文件中,原则上可用穷举法(rty对应的穷举为:rty、ryt、try、tyr、ytr、yrt),但考虑到破译速度,采用如下方法。
注意到单词列表中不存在组成字符完全相同的单词(如Hack12与Hack21包含完全相同的字符),因此将单词中的字符进行重组再进行比较,例如,try单词重组为rty(按ASCⅡ码顺序),这样不管打乱的单词是什么顺序,只要是由r、t、y三个字母组成的均破译为try,大大提高破译速度。程序中借助二叉排序树以进一步提高查找效率,二叉排序树左子树(如果有)上的节点对应的值均小于根节点的值,右子树(如果有)上的节点对应的值均大于根节点的值。
函数中使用的符号定义如下: #define NumberofWords
1275//单词总数 #define MaxLength 10//最长单词所含字符数
char WordList[NumberofWords][MaxLength];//存储单词列表
int cmp(Node *q,Node *p);//q与p比较。p小,返回负值;P大返回正值:相等,返回0
typedef struct Node(//二叉树节点 char *eleLetters;//重组后的字符串
int index;//对应单词表中的下标 struct Node
*lChiId,*rChiid;//左右子节点 }Node; [C代码]
void reCompose(Node *p,char *temp)
//重纰,亦即将temp字符串中的字符升序排序,存储于p节点中 //采用直接插入排序法
{ char c; strcpy(p->eleLetters,temp);//
int len=strlen(temp); int i,j,k;
for(i=0;i<len-1;i++){ k=i;
for(j=i+1;j<lan;j++){
if(p->eleLetters[j]<P->eleLetters[k])k=J; }
if({{U}} (1) {{/U}}){ C=P->eleLetters[i];
P->eleLetters[i]=P->eleLetters[k];
P->eleLetters[k]=c; }//if }//for
}; int find(Node root,char *temp)
//在二叉排序树root中查找与temp匹配的单词。
//若匹配返回相应单词在WordList中下标;若查找失败,返回-1 {
Node *P,*q; int flag; P={{U}} (2)
{{/U}};//临时存储 reCompose(p,temp);//将temp重组
q=root; while((flag={{U}} (3) {{/U}})&&q
!=NULL){ if(flag<0){//搜索左子树 q=q->lChiid;
}else(//搜索右子树 q=q->rChild; }
}//while if(flag==0){//找到匹配的,保存下标
return{{U}} (4) {{/U}}; } }
if({{U}} (5) {{/U}}){//查找失败
printf("cant unscramble the following word:%s",temp);;
return -1; } };
填空题[说明] 打印输出10行杨晖三角形。形式如下:
杨晖三角形:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
1 8 28 56 70 56 28 8 1
1 9 36 84 126 126 84 36 9 1
class yanghui
{
public static void main (String args [] )
{
int i, j;
{{U}} (1) {{/U}}
int yanghui [] [];
System. out. println( “杨晖三角形:” );
yanghui = new int [ yhleve1] [];
for(i =0;i < yanghui, length; i + + )
yanghui[i] = new int [i + 1];
{{U}}(2) {{/U}}
for({{U}} (3) {{/U}})
{
yanghui [i] [0] = 1;
for(j = 1 ;j < yanghui[i], length - 1 ;j + + )
yanghui[i] [j] = yanghui[i - 1] [j - 1] + yanghui[i - 1] [j];
yanghui[i] [yanghui[i]. length - 1 ] = 1;
}
for ( i=0; i < yanghui. length; i + + )
{
for(j =0;j < yanghui[i]. length; j + + )
{{U}} (4) {{/U}}
System. out. println( );
}
}
}
填空题[说明]若要在N个城市之间建立通信网络,只需要N-1条线路即可。如何以最低的经济代价建设这个网络,是一个网的最小生成树的问题。现要在8个城市间建立通信网络,其间拓扑结构如图所示,边表示城市间通信线路,边上标示的是建立该线路的代价。无向图用邻接矩阵存储,元素的值为对应的权值。考虑到邻接矩阵是对称的且对角线上元素均为0,故压缩存储,只存储上三角元素(不包括对角线)。现用Prim算法生成网络的最小生成树。由网络G=(V,E)构造最小生成树T=(U,TE)的Prim算法的基本思想是:首先从集合V中任取一顶点放入集合U中,然后把所有一个顶点在集合U里、另一个顶点在集合V-U里的边中,找出权值最小的边(u,v),将边加入TE,并将顶点v加入集合U,重复上述操作直U=V为止。函数中使用的预定义符号如下:#defineMAX32768/*无穷大权,表示顶点间不连通*/#defineMAXVEX30/*图中顶点数目的最大值*/typedefstructintStartVex,StopVex;/*边的起点和终点*/floatweight;/*边的权*/Edge;typedefstructcharvexs[MAXVEX];/*顶点信息*/floatarcs[MAXVEX*(MAXVEX-1)/2];/*邻接矩阵信息,压缩存储*/intn;/*图的顶点个数*/Graph;[函数]voidPrimMST(Graph*pGraph,Edgemst[])inti,j,k,min,vx,vy;floatweight,minWeight;Edgeedge;for(i=0;i<pGraph->n-1;i++)mst[i].StartVex=0;mst[i].StopVex=i+1;mst[i].weight=pGraph->arcs[i];for(i=0;i<______;i++)/*共n-1条边*/minWeight=(float)MAX;min=i;/*从所有边(vx,vy)中选出最短的边*/for(j=i;j<pGraph->n-1;j++)if(mst[j].weight<minWeight)minWeight=______;min=j;/*mst[min]最短的边(vx,vy),将mst[min]加入最小生成树*/edge=mst[min];mst[min]=mst[i];met[i]=edge;vx=______;/*vx为刚加入最小生成树的顶点下标*//*调整mst[i+1]到mst[n-1]*/for(j=i+1;j<pGraph->n-1;j++)vy=mst[j].StopVex;if______/*计算(vx,vy)对应的边在压缩矩阵中的下标*/k=pGraph->n*vy-vy*(vy+1)/2+vx-vy-1;elsek=pGraph->n*vx-vx*(vx+1)/2+vy-vx-1;weight=______;if(weight<mst[j].weight)mst[j].weight=weight;mst[j].StartVex=vx;
填空题[说明]欲开发一个绘图软件,要求使用不同的绘图程序绘制不同的图形。以绘制直线和圆形为例,对应的绘图程序如下表所示。不同的绘图程序DP1DP2绘制直线draw_a_line(x1,y1,x2,y2)drawline(x1,x2,y1,y2)绘制圆draw_a_circle(x,y,r)drawcircle(x,y,r)该绘图软件的扩展性要求,将不断扩充新的图形和新的绘图程序。为了避免出现类爆炸的情况,现采用桥接(Bridge)模式来实现上述要求,得到如下图所示的类图。某绘图软件类图[Java代码]________Drawing{________;________;classDP1{staticpublicvoiddraw_aline(doublex1,doubley1,doublex2,doubley2){/*代码省略*/}staticpublicvoiddraw_a_circle(doublex,doubley,doubler){/*代码省略*/}};classDP2(staticpublicvoiddrawline(doublex1,doublex2,doubley1,doubley2){/*代码省略*/}staticpublicvoiddrawcircle(doublex,doubley,doubler){/*代码省略*/}};classViDrawingimplementsDrawing{public{/*代码省略*/}public{________;}classV2DrawingimplementsDrawing{public{/*代码省略*/}public{________;}};abstractclassShape{privateDrawing_dp;________Shape(Drawingdp){_dp=dp;}public{_dp.drawLine(x1,y1,x2,y2);}public{_dp.drawCircle(x,y,r);}classRectangleextendsShape{privatedoublex1,x2,_y1,_y2;publicRectangle(Drawingdp,doublex1,doubley1,doublex2,doubley2){/*代码省略*/}publicvoiddraw(){/*代码省略*/}};classCircleextendsShape{privatedouble_x,_y,_r;publicCircle(Drawingdp,doublex,doubley,doubler){/*代码省略*/}publicvoiddraw(){drawCircle(_x,_y,_r);}
填空题[说明]计算一个整数数组a的最长递增子序列长度的方法描述如下:假设数组a的长度为n,用数组b的元素b[i]记录以a[i](0≤i<n”)为结尾元素的最长递增子序列的长度为;其中b[i]满足最优子结构,可递归定义为:[C代码]下面是算法的C语言实现。(1)常量和变量说明a:长度为n的整数数组,待求其最长递增子序列b:长度为n的数组,b[i]记录以a[i](0≤i<n”)为结尾元素的最长递增子序列的长度,其中0≤i<nlen:最长递增子序列的长度i,j:循环变量temp:临时变量(2)C程序#jnclude<stdio,h>mtmaxL(int*b,mtn){mtI,temp=0for(i=0;i<n;i++){(b[i]>temp)temp=b[i]returntemp;intmain(){intn,a[100],b[100],i,j,len;scanf("%d",for(i=0;i<n;i++){scanf("%d",________:for(i=1;i<n;i++){for(j=0,len=0;________;j++){if(________}Printf("len:%d\n",maxL(b,n))Primtf("\n")}
填空题[问题1]利用存在的依赖关系构造一个图书馆的对象模型。
填空题[问题3]使用ORDB的查询语言,分别写出下列查询的SELECT语句;1)检索每个学生的学习课程和成绩。2)检索至少有一门课程的求学地与籍贯在同一城市的学生的学号和姓名。
填空题
阅读下列函数说明和C代码, [说明]
所谓货郎担问题,是指给定一个无向图,并已知各边的权,在这样的图中,要找一个闭合回路,使回路经过图中的每一个点,而且回路各边的权之和最小。
应用贪婪法求解该问题,程序先计算由各点构成的所有边的长度(作为边的权值),按长度大小对各边进行排序后,按贪婪准则从排序后的各边中选择组成回路的边,贪婪准则使得边的选择按各边长度从小到大选择。
函数中使用的预定义符号如下: #define M 100
typedef struct{/*x为两端点p1、p2之间的距离,p1、p2所组成边的长度*/ float x;
int p1,p2; }tdr; typedef
struct{/*p1、p2为和端点相联系的两个端点,n为端点的度*/ int n,p1,p2;
}tr; typedef struct{/*给出两点坐标*/ float
x,y; }tpd; typedef int tl[M];
int n=10; [函数] float distance(tpd a,tpd
b);/*计算端点a、b之间的距离*/ void sortArr(tdr a[M],int m);
/*将已经计算好的距离关系表按距离大小从小到大排序形成排序表,m为边的条数*/ int isCircuit(tr
r[M],int i,int j); /*判断边(i,j)选入端点关系表r[M]后,是否形成回路,若形成回路返回0*/
void selected(tr r[M],int i,int j);/*边(i,j)选入端点关系表r*/
void course(tr r [M],tl l[M]);/*从端点关系表r中得出回路轨迹表*/
void exchange(tdr a[M],int m,int b);
/*调整表排序表,b表示是否可调,即是否有长度相同的边存在*/ void travling(tpd pd
[M],int n,float dist,tl locus[M]) /*dist记录总路程*/
{ tdr dr[M];/*距离关系表*/ tr r[M];/*端点关系表*/
int i,j,k,h,m;/*h表示选入端点关系表中的边数*/ int
b;/*标识是否有长度相等的边*/ k=0; /*计算距离关系表中各边的长度*/
for(i=1;i<n; i++){ for(j=i+1;J<=n;j++){
k++; dr[k].x={{U}} (1) {{/U}};
dr[k].pl=i; dr[k].p2=j; }
} m=k;
sortArr(dr,m);/*按距离大小从小到大排序形成排序表*/ do{
b=1; dist=0; k=h=0: do{
k++; i=dr[k].p1; j=dr[k].p2;
if((r(i].n<=1)(r[j].n<=1)){/*度数不能大于2*/
if{{U}} (2) {{/U}}{
/*若边(i,j)加入r后形成回路,则不能加入*/ {{U}} (3) {{/U}};
h++; dist+=dr[k].x; }else
if{{U}} (4) {{/U}}{ /*最后一边选入r成回路,则该边必须加入且得到解*/
selected(r,i,j); h++:
dist+=dr[k].x; } }
}while((k !=n) (h !=n));
if(h==n){/*最后一边选入构成回路,完成输出结果*/ course(r,locus);
}else(/*找不到解,调整dr,交换表中边长相同的边在表中的顺序,并将b置0*/ {{U}}
(5) {{/U}}; } }while(!b);
}
填空题[说明] 设计一个计时程序。该程序用户界面由一个文本框(text 1),两个按钮——命令按钮1 (Command 1)按钮、命令按钮(Command 2)组成。程序运行后,用户按开始按钮,则开始计时,文本框中显示秒数,按停止按钮,则计时停止。单击窗口则退出。 Option Explicit Dim I Private Sub Command1 _ Click( ) i=0 Timer1. Interval = 1000 (1) End Sub Private Sub Command2_ Click( ) Timer1. Enabled = False End sub Private Sub Form Click( (2) End Sub Private Sub Form _Load( ) Timer1. Enabled = False (3) End Sub Private Sub Timer1 _ Timer( ) i=i+1 (4) End Sub
填空题阅读下列说明和C程序,将应填入 (n) 处的字句写在对应栏中。 [说明] 借助一个栈结构,可实现二叉树的非递归遍历算法。InOrderTraverse数实现中序非递归遍历,遍历 过程如下: 若不是空树,根节点入栈,进入左子树;若已经是空树,则栈顶元素出栈,访问该元素(根节点),进入该节点的右子树,继续直到遍历完成。 函数中使用的预定义符号如下: typedef struct BiTNode int data; struct BiTNode *iChiid,*rChiid; BiTNode,*BiTree; typedef struct SNode/*链栈的节点类型*/ BiTree elem; struct SNode *next; SNode; [函数] int InOrderTraverse(BiTree root) BiTree P; SNode *q,*stop=NULL;/*不带头节点的单链表作为栈的存储结构*/ P=root; while(p !=NULL || stop !=NULL) if( (1) ) /*不是空树*/ q=(SNode*)malloc(sizeof q); if(q==NULL)return-1; /*根节点指针入栈*/ (2) ; q->elem=P; stop=q; P= (3) ; /*进入根的左子树*/ else q=stop; (4) ; /*栈顶元素出栈*/ printf("%d|,q->elem->data); /*防问根节点*/ P= (5) ; /*进入根的右子树*/ free(q); /*释放原栈顶元素*/ /*if*/ /*while*/ return 0; /*InOrderTraverse*/
填空题阅读下列说明和E-R图,回答问题1至问题3,将解答填入对应栏内。[说明]设有下列关于学生成绩管理系统的E-R图(见图2-1)。图中矩形表示实体,圆表示属性,双圆表示关键字属性,菱形表示实体间的联系。假定已通过下列SQL语言建立了基本表:CREATETABLESTUDENT(SNoCHAR(6)NOTNULLUNIQUE,SNameCHAR(20),SexCHAR(1),DeptCHAR(20),AgeSMALLINT);CREATETABLECOURSE(CNoCHAR(6)NOTNULLUNIQUE,CNameCHAR(20),HourSMALLINT,CreditSMALLINT);CREATETABLESC(SNoCHAR(6),CNoCHAR(6),GRADESMALLINT,PRIMARYKEY(SNo,CNo));为了答题的方便,图中的实体和属性同时给出了中英文两种名字,回答问题时只须写出英文名即可。填充下列SQL程序5.1~5.4中的(1)~(6),使它们分别完成以下查询功能:程序5.1:检索选修所有课程的学生姓名。程序5.2:给出全体学生人数。程序5.3:按学号给出每个学生的平均成绩。程序5.4:按学号给出每个学生选修课程的门数。[程序5.1]SELECTSNameFROMSTUDENTWHERE(1)(SELECTFROMCOURSEWHERE(2)(SELECT*FROMSCWHERE(3)))[程序5.2]SELECT(4)FROMSTUDENT[程序5.3]SELECT(5)FROMSCGROUPBYSNO[程序5.4]SELECT(6)FROMSCGROUPBYSNO
填空题若另有表Teach(CName,TName)存储教师任课情况,Tname表示教师名。用SQL创建一个含有学号、姓名、课程名、成绩、任课教师名的“主修专业为计算机CS”的学生成绩视图,并要求进行修改、插入操作时保证该视图只有计算机系的学生。请在SQL语句空缺处填入正确的内容。 CREATE VIEW SG (1) SELECT Student.SNo,SName,Grade,Course.CName,TName FROM Student,Grade,Teach, WHERE (2) AND (3) AND Major='cs', (4) ;
填空题[说明] 设计一个计时程序。该程序用户界面由一个文本框(text 1),两个按钮——命令按钮1 (Command 1)按钮、命令按钮(Command 2)组成。程序运行后,用户按开始按钮,则开始计时,文本框中显示秒数,按停止按钮,则计时停止。单击窗口则退出。
Option Explicit
Dim I
Private Sub Command1 _ Click( )
i=0
Timer1. Interval = 1000
{{U}} (1) {{/U}}
End Sub
Private Sub Command2_ Click( )
Timer1. Enabled = False
End sub
Private Sub Form Click(
{{U}} (2) {{/U}}
End Sub
Private Sub Form _Load( )
Timer1. Enabled = False
{{U}} (3) {{/U}}
End Sub
Private Sub Timer1 _ Timer( )
i=i+1
{{U}} (4) {{/U}}
End Sub
填空题#include <stdio. h>
void main( )
{ int digit;
long in , s;
seanf(" % Id",
{{U}} (1) {{/U}};
{{U}} (2) {{/U}};
while(in >0) {
{{U}} (3) {{/U}};
s = s + digit* digit;
{{U}} (4) {{/U}};
}
pfinff( "sum = % 1dn", s );
}
填空题[说明] 这是一个用户名校验程序,如用户名正确,即输出欢迎字样,否则,弹出警告窗并直接退出程序。下面是实现上述功能的程序,请填空。“Option Explicit”此语句的作用:强制显示声明 Dim UserName (2) As String Dim Flag As Boolean (1) Private Sub Form _ Load( ) UserName (0) = "AA": UserName (1) = "BB": UserName(2) = "CC" Flag = False inputName = InputBox( “请输入名称:“,”身份确认”“,”) Dim i As Integer For i = 0 To False If inputName = UserName(i) Then (2) End If Next i If (3) Then MsgBox “用户身份确失败!退出应用”, vbOKOnly, “警告” End End If End Sub Private Sub Form_ Paint( ) (4) End Sub
填空题[说明] Huffman树又称最优二叉树,是一类带权路径长度最短的树,在编码中应用比较广泛。 构造最优二叉树的Huffman算法如下: ①根据给定的n各权值w1,w2,…,wn构成n棵二叉树的集合F=T1,T2,…,Tn,其中每棵树Ti中只有一个带权为wi的根节点,其左右子树均空。 ②在F中选取两棵根节点的权值较小的树作为左右子树,构造一棵新的二叉树,置新构造二叉树的根节点的权值为其左右子树根节点的权值之和。 ③从F中删除这两棵树,同时将新得到的二叉树加入到F中。 重复②③,直到F中只剩一棵树为止。 函数中使用的预定义符号如下: #define INT_MAX 10000 #define ENCODING LENGTH 1000 typedef enum(none,left_chiid, right chiid Which; /*标记是左孩子还是右孩子*/ typedef char Elemtype; typedef struct TNode//Huffman树节点 Elemtype letter; int weight; //权值 int parent; //父节点 Which sigh; char *code; //节点对应编码 HTNode,*HuffmanTree; int n; char coding[50];//储存代码 [函数] void Select(HuffmanTree HT, int end, int *s1, int *s2) /*在0~END之间, 找出最小和次小的两个节点序号,返回s1、s2*/ int i; int min1= INT_MAX; int min2 = INT_MAX; for (i = 0; i <= end; i++) /*找最小的节点序号*/ if((______) min1 = HT[i].weight; for(i = 0; i <= end; i++) *找次小节点的序号*/ if((HT[i].parent == 0) min2 = HT[i].weight; void HuffmanTreeCreat(HuffmanTree int m = 2 * n - 1; int s1,s2; for(i = n; i < m; i++) Select(______); HT[s1].parent = i; HT[s2].parent = i; HT[s1].sigh = left_child; HT[s2].sigh = right_child; HT[i].weight = ______; void HuffmanTreeEncoding(char sen[],HuffmanTree HT) /*将句子进行编码*/ int i = 0; int j; while(sen[i] != '/0') for(j = 0; j < n; j++) if (HT[j].letter == sen[i]) /*字母匹配则用代码取代*/ strcat(coding, ______); break; i++; if (sen[i] == 32) i++; printf("/n%s",coding);
填空题
阅读下列函数说明和C++代码,将应填入{{U}} (n) {{/U}}处的字句写在对应栏内。
[说明]
在销售系统中常常需要打印销售票据,有时需要在一般的票据基础上打印脚注。这样就需要动态地添加一些额外的职责。如下展示了Decorator(修饰)模式。SalesOrder对象使用一个SalesTicket对象打印销售票据,先打印销售票据内容,然后再打印脚注。图5-1显示了各个类间的关系。以下是C++语言实现,能够正确编译通过。
[图5-1] [C++代码]
class Component{ public: {{U}} (1)
{{/U}}void prtTicket()=0; }; class
SalesTicket:public Component{ public: void
prtTicket(){ cout<<"Sales Ticket!"<<endl; }
}; class Decorator:public Component{
public: virtual void prtTicket();
Decorator(Component *myC); private: {{U}}
(2) {{/U}}myComp; };
Decorator::Decorator(Component *myC) {
myComp=myC; } void Decorator::prtTicket()
{ myComp->prtTicket(); }
class Footer:public Decorator{ public:
Footer(Component *myC); void prtTicket();
void prtFooter(); };
Footer::Footer(Component *myC):{{U}} (3) {{/U}}{}
void Footer::prtFooter() {
cout<<"Footer"<<endl; } void
Footer::prtTicket() { {{U}} (4)
{{/U}}; prtFooter(); }
class SalesOrder{ public: void
prtTicket(); }; void SalesOrder::prtTicket()
{ Component *myST;
myST=new Footer({{U}} (5) {{/U}});
myST->prtTicket(); }
填空题阅读以下说明和C++代码,[说明]现要编写一个画矩形的程序,目前有两个画图程序:DP1和DP2,DP1用函数draw_a_line(x1,y1,x2,y2)画一条直线,DP2则用drawline(x1,x2,y1,y2)画一条直线。当实例化矩形时,确定使用DP1还是DP2。为了适应变化,包括“不同类型的形状”和“不同类型的画图程序”,将抽象部分与实现部分分离,使它们可以独立地变化。这里,“抽象部分”对应“形状”,“实现部分”对应“画图”,与一般的接口(抽象方法)与具体实现不同。这种应用称为Bridge(桥接)模式。图6-1显示了各个类间的关系。[图6-1]这样,系统始终只处理3个对象:Shape对象、Drawingg对象、DP1或DP2对象。以下是C++语言实现,能够正确编译通过。[C++代码]classDP1public:staticvoiddraw_a_line(doublex1,doubley1,doublex2,doubley2)//省略具体实现;classDP2public:staticvoiddrawline(doublex1,doublex2,doubley1,doubley2)//省略具体实现;classDrawingpublic:(1)voiddrawLine(doublex1,doubley1,doublex2,doubley2)=0;;classV1Drawing:publicDrawingpublic:voiddrawLine(doublex1,doubley1,doublex2,doubley2)DP1::draw_a_line(x1,y1,x2,y2);;classV2Drawing:publicDrawingpublic:voiddrawLine(doublex1,doubley1,doublex2,doubley2)(2);classShapeprivatc:(3)dp;public:Shape(Drawing*dp);virtualvoiddraw()=0;voiddrawLine(doublex1,doubley1,doublex2,doubley2);;Shape::Shape(Drawing*dp)_dp=dp;voidShape::drawLine(doublex1,doubley1,doublex2,doubley2)//画一条直线(4);classRectangle:publicShapeprivatc:double_x1,_y1,_x2,_y2;public:Rectangle(Drawing*dp,doublex1,doubley1,doublex2,doubley2);voiddraw();;Rectangle::Rectangle(Drawing*dp,doublex1,doubley1,doublex2,doubley2):(5)_x1=x1;_y1=yl;_x2=x2;_y2=y2;voidRectangle::draw()//省略具体实现
填空题
阅读以下函数说明和Java代码, [说明]
现要编写一个画矩形的程序,目前有两个画图程序:DP1和DP2,DP1用函数draw_a_line(x1,y1,x2,y2)画一条直线,DP2则用drawline(x1,x2,y1,y2)画一条直线。当实例化矩形时,确定使用DPI还是DP2。
为了适应变化,包括“不同类型的形状”和“不同类型的画图程序”,将抽象部分与实现部分分离,使它们可以独立地变化。这里,“抽象部分”对应“形状”,“实现部分”对应“画图”,与一般的接口(抽象方法)与具体实现不同。这种应用称为Bridge(桥接)模式。图7-1显示了各个类间的关系。
[图7-1]
这样,系统始终只处理3个对象:Shape对象、Drawing对象、DP1或DP2对象。以下是JAvA语言实现,能够正确编译通过。
[Java代码] //DP1.Java文件 public
class DPI{ static public void draw_a_line(double x1,double y1,
double x2,double y2){ //省略具体实现
} } //DP2.java文件 public
class DP2{ static public void drawline(double x1,double y1,
double x2,double y2){ //省略具体实现
} } //Drawing.java文件
{{U}} (1) {{/U}}public class Drawing{ abstract
public void drawLine(double x1,double y1,double x2,double y2);
} //V1Drawing.java文件 public class
V1Drawing extends Drawing{ public void drawLine(double
x1,double y1,double x2,double y2){
DP1.draw_a_line(x1,y1,x2,y2); } }
//V2Drawing.java文件 public class V2Drawing
extends Drawing{ public void drawLine(double x1,double y1,
double x2,double y2){//画一条直线 {{U}} (2)
{{/U}}; } }
//Shape.java文件 abstract public class Shape{
abstract public void draw(); private{{U}} (3)
{{/U}}dp; Shape(Drawing dp){ _dp=dp;
} protected void drawLine(double x1,double y1,
double x2,double y2){ {{U}} (4)
{{/U}}; } }
//Rectangle.java文件 public class Rectangle extends Shape{
private double_x1,_x2,_y1,_y2; public
Rectangle(Drawing dp, double x1,double y1,
double x2,double y2){ {{U}}(5) {{/U}};
_x1=x1;_x2=x2; _y1=y1;_y2=y2; }
public void draw(){ //省略具体实现
} }
