设计模式命令模式_第1页
设计模式命令模式_第2页
设计模式命令模式_第3页
设计模式命令模式_第4页
设计模式命令模式_第5页
已阅读5页,还剩18页未读 继续免费阅读

下载本文档

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

文档简介

第七章命令模式七.一问题地提出七.二命令模式七.三深入理解命令模式七.四应用示例七.一问题地提出顾名思义,命令模式一定是有命令发送者,命令接收者。命令发送者负责发送命令,命令接收者负责接收命令并完成具体地工作。例如老师通知学生打扫卫生,老师是命令发送者,学生是命令接收者,当学生接到命令后,完成分担区地清扫工作。再如完成科研项目过程,负责要求某月某日之前需要完成某部分工作,负责相当于命令发送者,项目参加者相当于命令接收者,当接到命令后,需要按规定日期完成所属工作。毫无疑问"命令"形式在生活是普遍存在地,那么在计算机如何描述呢?命令模式为我们提出了较好地设计思路。一.抽象类图七.二命令模式二.类图说明•Imander:抽象命令者,是一个接口,规定了用来封装请求地若干个方法。•Concretemander:具体命令发送者,即命令源,它是实现命令接口地类地实例。如上文地Teacher类。•Invoker:请求者,具体命令地管理与维护类。请求者是一个包含"命令接口"变量地类地实例。请求者地"命令"接口地变量可以存放任何具体命令地引用,请求者负责调用具体命令,让具体命令执行那些封装了请求地方法。•Receiver:命令接收者,是一个类地实例,该实例负责执行与请求有关地操作。如上文地Student类。七.三深入理解命令模式七.三.一命令集管理考虑求任意多边形面积问题(给出各点坐标)。具体代码如下所示。一.计算面积类PolyonCalcclassPoint{ floatx,y; publicPoint(floatx,floaty){ this.x=x;this.y=y; }}classPolyonCalc{ publicfloatgetArea(Pointpt[]){ floats; intsize=pt.length; if(pt.length<三)return零; s=pt[零].y*(pt[size-一].x-pt[一].x); for(inti=一;i<size;i++) s+=pt[i].y*(pt[(i-一)].x-pt[(i+一)%size].x); return(float)s/二; }}二.抽象命令发送者ImanderinterfaceImander{ floatcalc();}

三.具体面积命令发送者AreamanderclassAreamanderimplementsImander{ PolyonCalccalc; Pointpt[]; publicAreamander(Pointpt[],PolyonCalccalc){ this.pt=pt;this.calc=calc; } publicfloatcalc(){ returncalc.getArea(pt); }}四.命令管理者manderManage 相当于命令请求者Invoke,具体代码如下所示。classmanderManage{ ArrayList<Imander>list=newArrayList(); publicvoidadd(Imanderc){ list.add(c); } publicvoidexecutemand(){ for(inti=零;i<list.size();i++){ floatvalue=list.get(i).calc(); System.out.println("Theareais:"+value); } }} 可知:定义了Imand命令地集合成员变量list,定义了添加命令消息地add()方法以及整体执行命令集地executemand()方法。读者可以根据需要自行丰富该命令管理类地功能。五.一个简单地测试类publicclassTest三{ publicstaticvoidmain(String[]args){ manderManagemanage=newmanderManage();//定义命令管理者 PolyonCalccalc=newPolyonCalc(); //定义命令接收者 Pointpt[]=newPoint[三]; pt[零]=newPoint(零,零);pt[一]=newPoint(一,零);pt[二]=newPoint(零,一);//定义第一个三角形坐标 Areamander=newAreamander(pt,calc); //定义第一条面积命令 manage.add(); //加入命令管理者 pt=newPoint[三]; pt[零]=newPoint(零,零);pt[一]=newPoint(二,零);pt[二]=newPoint零,二);//定义第二个三角形坐标 Areamander二=newAreamander(pt,calc); //定义第二条面积命令 manage.add(二); //加入命令管理者 manage.executemand(); //统一执行 }}七.三.二加深命令接口定义地理解可能有许多读者认为命令接口很好定义,其实不然,还是用七.三.一实例加以说明,假设现在要增加求多边形周长地功能,该如何实现呢?方法一:由于要求多变形地面积与周长,有两个功能,因此命令接口也要定义两个方法,如下所示。interfaceImander{ floatcalcArea(); //求面积 floatcalcLen(); //求周长}毫无疑问,命令接口内容变了,许多已经实现地代码都要行改变。而且,将来若需求分析发生变化,例如若计算多边形重心坐标,按照此思路,还需要修改命令接口,因此这种命令接口思考方式仅仅处于底层状态,是不可取地,有关地具体代码也就不列举了。好地思路是下述地方法二。

方法二://定义抽象命令接口ImanderinterfaceImander{ floatcalc();}可以看出,虽然要实现求面积与周长两个功能,但定义地命令接口内容不变。那么,它与方法一地定义有什么不同呢?从浅层角度讲,方法一是把"计算面积","计算周长","计算XXX"等做为接口内容地,所以接口方法一定是多个。方法二是把"计算"做为接口内容,而不管"XXX"是什么,所以仅定义一个接口方法即可。从深层角度讲,我们定义地抽象命令接口内容不应仅适用于计算多边形地面积,周长运算,还应适用于复数,积分等尽可能多地计算功能。因此命令接口是更高层次地抽象,读者一定要细心把握。七.三.三命令模式与JDK处理考虑布局管理器示例。当按"FlowLayout演示"按钮,界面如图七-五a所示;当按"BorderLayout演示"按钮,界面如图七-五b所示。图七-五aFlowLayout演示界面 图七-五bBorderLayout演示界面方法一:publicclassMyFrameextendsJFrame{ JPanelcontent=newJPanel(); ActionListenera=newActionListener(){ //命令接收者对象 publicvoidactionPerformed(ActionEvente){ content.removeAll(); //清除所有子窗口 content.setLayout(newFlowLayout()); //设置流式布局管理器 content.add(newJButton("一"));content.add(newJButton("二")); content.add(newJButton("三"));content.add(newJButton("四")); content.add(newJButton("五")); content.updateUI(); } }; ActionListenera二=newActionListener(){ //命令接收者对象 publicvoidactionPerformed(ActionEvente){ content.removeAll(); //清除所有子窗口 content.setLayout(newBorderLayout());//设置方位布局管理器 content.add(newJButton("北"),BorderLayout.NORTH); content.add(newJButton("南"),BorderLayout.SOUTH); content.add(newJButton("西"),BorderLayout.WEST); content.add(newJButton("东"),BorderLayout.EAST); content.add(newJButton(""),BorderLayout.CENTER); content.updateUI(); } }; publicvoidinit(){ JPanelp=newJPanel(); JButtonbtn=newJButton("FlowLayout演示"); //定义源(命令源)对象 JButtonbtn二=newJButton("BorderLayout演示"); //定义源(命令源)对象 p.add(btn);p.add(btn二);

add(p,BorderLayout.NORTH); add(content);

btn.addActionListener(a); btn二.addActionListener(a二);

setSize(三零零,一五零); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); } publicstaticvoidmain(String[]args){ newMyFrame().init(); }方法二:interfaceIReceiver{//抽象命令接收者方法定义,此接口方法一不需要 publicvoidresponse();}classMyFrameextendsJFrameimplementsActionListener{ JPanelcontent=newJPanel(); classFlowBtnextendsJButtonimplementsIReceiver{//FlowBtn即是命令发送者,又是接收者 publicFlowBtn(Stringname){ super(name); } publicvoidresponse(){ content.removeAll(); content.setLayout(newFlowLayout()); content.add(newJButton("一"));content.add(newJButton("二")); content.add(newJButton("三"));content.add(newJButton("四")); content.add(newJButton("五")); content.updateUI(); } } classBorderBtnextendsJButtonimplementsIReceiver{//BorderBtn即是命令发送者,又是接收者 publicBorderBtn(Stringname){ super(name); } publicvoidresponse(){ content.removeAll(); content.setLayout(newBorderLayout()); content.add(newJButton("北"),BorderLayout.NORTH); content.add(newJButton("南"),BorderLayout.SOUTH); content.add(newJButton("西"),BorderLayout.WEST); content.add(newJButton("东"),BorderLayout.EAST); content.add(newJButton(""),BorderLayout.CENTER); content.updateUI(); } } publicvoidinit(){ JPanelp=newJPanel(); FlowBtnbtn=newFlowBtn("FlowLayout演示"); BorderBtnbtn二=newBorderBtn("BorderLayout演示"); p.add(btn);p.add(btn二);

add(p,BorderLayout.NORTH); add(content);

btn.addActionListener(this); btn二.addActionListener(this);

setSize(三零零,一五零); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); } publicvoidactionPerformed(ActionEvente){ IReceiverobj=(IReceiver)e.getSource(); obj.response(); } publicstaticvoidmain(String[]args){ newMyFrame().init(); }}与方法一相比,主要有以下两点需要加深理解。 •本示例有效命令源是JButton地派生类FlowBtn,BorderBtn类型地对象。 •FlowBtn,BorderBtn两个类即从JButton派生,又实现了抽象接收者接口IReceiver,就可以看出这两个类地对象即是命令发送者,又是命令接收者,这一点读者要尤为加以思考。 •FlowBtn,BorderBtn按钮对象对应同一个方法actionPerformed(),那么如何获得具体地命令接收者对象引用呢?巧妙通过"IReceiveobj=(IReceive)e.getSource()"即可完成相应功能,避免了不必要地if或switch语句。七.三.四命令模式与多线程考虑这样应用,功能是连续接收字符串信息,其格式为:"姓名:信息",例如:"zhang:Hello"表明该信息是zhang发送地,信息内容是hello。假设zhang同志发送地信息非常重要,因此,当接收到该同志地信息时,一方面要把该信息显示在屏幕上,一方面把该信息以EMAIL形式传送给有关士,仿真这一过程。一.信息接收功能(命令发送者)interfaceISource{ booleanisbFire(); voidsetbFire(booleanbFire);}classMsgsrcimplementsISource{ Stringmsg; booleanbFire; //重要信息标识变量 publicStringgetMsg(){ returnmsg; } publicbooleanisbFire(){ returnbFire; } publicvoidsetbFire(booleanbFire){ this.bFire=bFire; } publicvoide(Stringmsg){ this.msg=msg; if(msg.equals("zhang:"))//如果是zhang同志来地信息,非常重要 bFire=true; //则至重要信息标识变量为true //其它功能代码 }}二.特殊信息处理功能(命令接收者)interfaceIReceiver{ voidprocess(ISourcesrc);}classShowReceiveimplementsIReceiver{ publicvoidprocess(ISourcesrc){ Msgsrcobj=(Msgsrc)src; System.out.println(obj.getMsg()); }}classEMailReceiveimplementsIReceiver{ publicvoidprocess(ISourcesrc){ System.out.println("thisisEMailprocess"); }}三.命令监测功能(相当于Invoker)//定义抽象命令接口ImandinterfaceImand{ publicvoidnoticemand();}

//定义具体命令类classmandimplementsImand{ IReceiverrvr; ISourcesrc; publicmand(IReceiverrvr,ISourcesrc){ this.rvr=rvr; this.src=src; } publicvoidnoticemand(){ cess(src); }}//定义命令集管理类mandManageclassmandManageextendsThread{ Vector<Imand>v=newVector(); ISourcesrc; booleanbMark=true; publicmandManage(ISourcesrc){ this.src=src; } publicvoidaddmand(Imandc){ v.add(c); } publicvoidrun(){ while(bMark){ if(!src.isbFire()) //若非重要消息,返回 continue; for(inti=零;i<v.size();i++){//遍历命令集与,发送通知消息 v.get(i).noticemand(); } src.setbFire(false);//重要消息标识位复位 } }}四.一个测试类publicclassTest八{publicstaticvoidmain(Stringargs[])throwsException{ Msgsrcsrc=newMsgsrc();//定义源(发送者) ShowReceivervr=newShowReceive(); //定义接收者 EMailReceivervr二=newEMailReceive(); //定义接收者二 mand=newmand(rvr,src); //定义命令一 mand二=newmand(rvr二,src);//定义命令二

mandManagemanage=newmandManage(src);//定义命令集Invoke manage.addmand(); //命令集加入命令一 manage.addmand(二);//命令集加入命令二 manage.start(); //启动命令集监测线程

Strings[]={"li:aaa","zhang:hello","li:bbb"}; for(inti=零;i<s.length;i++){ src.e(s[i]); //仿真向命令源传送字符串 Thread.sleep(一零零零); } manage.bMark=false; //设置结束线程标识}}七.四应用示例例七-一简单记事本程序设计与实现。一.界面生成及初始化classMyFrameextendsJFrame{ JTextAreata=newJTextArea(); //文本区 FilecurFile=null; //当前打开文件对象privateAction[][]actions={ //四个响应类 {newNewAction(),newOpenAction(),newSaveAction(),newExitAction()}};privatevoidsaveFile(){ try{ FileOutputStreamout=newFileOutputStream(curFile); bytebuf[]=ta.getText().getBytes(); out.write(buf); out.close(); } catch(Exceptione){e.printStackTrace();}}privatevoidsavePathFile(){JFileChooserchooser=newJFileChooser();intret=chooser.showSaveDialog(MyFrame.this);if(ret!=JFileChooser.APPROVE_OPTION) return;try{ curFile=chooser.getSelectedFile();FileOutputStreamout=newFileOutputStream(curFile);out.write(ta.getText().getBytes());out.close(); }catch(Exceptionee){ee.printStackTrace();} }privatevoidpreProcess(){ if(curFile!=null){ saveFile(); return; } if(!ta.getText().equals("")) savePathFile(); }protectedJMenuBarcreateMenubar(){ JMenuBarmb=newJMenuBar(); //创建菜单条 String[]menuKeys={"File"}; String[][]itemKeys={{"New","Open","Save","Exit"}}; for(inti=零;i<menuKeys.length;i++){ JMenum=newJMenu(menuKeys[i]); //创建菜单 for(intj=零;j<itemKeys[i].length;j++){ JMenuItemmi=newJMenuItem(itemKeys[i][j]);//创建菜单项 mi.addActionListener(actions[i][j]);//菜单项添加消息响应 m.add(mi); //菜单添加菜单项 } mb.add(m); //菜单条添加菜单 } returnmb;} publicvoidinit(){ this.setJMenuBar(createMenubar()); //设置菜单 JScrollPanesp=newJScrollPane(ta); //设置滚动文本区 add(sp); //添加滚动面板 setSize(六零零,五零零); setVisible(true); } publicstaticvoidmain(String[]args){ newMyFrame().init(); }}二.响应类 //New响应类NewActionclassNewActionextendsAbstractAction{publicvoidactionPerformed(ActionEvente){preProcess(); //前处理ta.setText(""); //设文本区域内容为空curFile=null; //当前文件对象为nullMyFrame.this.setTitle("无标题");//设置标题}}//Open响应类OpenActionclassOpenActionextendsAbstractAction{publicvoidactionPerformed(Actio

温馨提示

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

评论

0/150

提交评论