可扩展的Java应用程序开发模式
上一篇 / 下一篇 2012-08-27 10:45:44 / 个人分类:Java
7\ s e G7V'?8f0?P.R0 摘要:这个程序最简单的版本是在主类中做每件事情,主类包含一些持有孩子姓名的数组和向量(Vector),一个另一个最简单的方法是为每个孩子创建一个对象,每个对象有一个象isFemal()这样的方法来帮助我们确定要显示的是男的还是女的。51Testing软件测试网 KfE#M,g1Mi\ v%t
51Testing软件测试网Y9AfA7z}[现在很多JAVA书籍,在介绍SWING的事件模型时,为了使JAVA初学者容易理解和上手,通常是在主类(自己的JFrame子类或JPanel)中 做所有事情:要么由主类作为监听器,在接口的方法中通过判定事件源来决定具体做何事;要么在主类中使用内隐类来实现监听器,(因为内隐类可以方便的访问主 类中的成员变量)。而很多JAVA初学者在往后的编程中也采用这种模式(至少我以前是这样的)。其实,这种做法虽然简单,却缺乏可读性、可扩展性和可维护 性。之前我看到了一篇关于这个问题的文章(来自于《JavaPro》),现整理出来与大家分享。51Testing软件测试网 ^ kRY^0`r!@;Z
@4X2iuG0~~0 下面我将用一个简单的例子来说明如何使用模式来解决这个问题。
w7D1h#|]7HjLf051Testing软件测试网_&X!B&W2xEkSL现在,假设我们要编写一个使用几个单选按钮从一个长列表中选择不同分组的程序。单击Female单选按钮时,只有女孩的名字被显示;当你点击Male按钮时,程序显示男孩的名字。51Testing软件测试网;bK*j;z;w Y$U)aOy
51Testing软件测试网*I R2X'{z"z*^6w这个程序最简单的版本是在主类中做每件事情,主类包含一些持有孩子姓名的数组和向量(Vector),一个另一个最简单的方法是为每个孩子创建一个对 象,每个对象有一个象isFemal()这样的方法来帮助我们确定要显示的是男的还是女的。在程序中我们把每个孩子的类称为Swimmer:51Testing软件测试网\ V"xvs)S
public class Swimmer{51Testing软件测试网1} aY&p5T,T*u4v3r private String name; u#l-ByR5~ j8Z*R3f0private int age;51Testing软件测试网#q$H*Ox2}8t;g [S private String club;51Testing软件测试网Z#J ?2~+_ W0|c\%Y1O private boolean female; 0BUdo7x;O-`@J0public Swimmer(String name,int age,String club,boolean female){ @}}0[G R&z![ g0this.name=name;51Testing软件测试网(Ig4kg#H@%b this.age=age; *{kv u1YB0this.club=club; :BUQ3b;POE,O0this.female=female;51Testing软件测试网Kouut w1X/DfV }51Testing软件测试网z)n1i1WM6e4K&?E public boolean isFemale(){ ,Tm T[ V0av$RG0return female;51Testing软件测试网5`/k0T4r"CQ;i Q }51Testing软件测试网f,rX/QR1_x,YBD public String getName(){ 6X)c ATo%R[{0return name;51Testing软件测试网s'Pf4l,ts } -vP"fD5tuq0public int getAge(){ 9d-{M8c/`tn X a0return age; %wd5s+ki'W0} k/jt'JDt0public String getClub(){ /J"y+lq6k6M)X:NA0return club; ic$yml)q0Gp |On0}51Testing软件测试网_\Mq3eMZ } |
下一步我们要做的是决定整个列表中的哪些孩子会被显示。我们可以在主用户接口类中做到这点,但是最好的是在一个叫做Swimmers的集合类中来做,这个类有一个getList()方法,它带有布尔型的参数来决定是男孩还是女孩:51Testing软件测试网oY"T:D+o7C\Y@g)e
//get a vector of swimmers who are (female)51Testing软件测试网8bT{!XI4u public Vector getList(boolean female){51Testing软件测试网U7E!h ?]&G c Vector v=new Vector(); i0H.uZ7ta|P0for(int i=0;i51Testing软件测试网+U+p2P Q zb*^-LR Swimmer swm=(Swimmer)kids.elementAt(i);51Testing软件测试网;nm.q7|fP if(swm.isFemal()==female) v.add(swm);51Testing软件测试网&EUN g+aq-k }51Testing软件测试网pe-d&c"Y6KquB return v; /z ^])F't&L0} |
TY'Y7{B^1y;u_0 我们又提供了一个不带参数的多态getList()方法来返回整个列表。
ZSELuGsI051Testing软件测试网n#pI]$B现在让我们进入程序中的第一个重要的部分,为了显示这些孩子的姓名,我们需要为三个单选按钮都添加一个事件监听器,使得每个都能显示出正确的孩子们:
9Ss8BykU~0public void actionPerformed(ActionEvent e){51Testing软件测试网(H]l*b*Z//listen for button clicks and do the right thing
"t \h"lh1G%i0Object bj=e.getSource();
?'`P4Kg i0if(obj==female) loadFemales();
'CV-Za9B0if(obj==male) loadMales();
%Y%d&[ dP2A/|0if(obj==both) loadBoth();51Testing软件测试网Y,b KAG
}51Testing软件测试网d |'@o4a
private void loadFemales(){51Testing软件测试网 u#y4K.R2C0A}hpm
//display female swimmers51Testing软件测试网e#[UJ8U7\D
Vector v=swimmers.getList(true);
%TNd+m*oH3nyR0loadList(v);
.WK:A6V;ed]C@0}51Testing软件测试网|U/e9l;Cjws1x0r
private void loadMales(){51Testing软件测试网^^"FRI7e
//display male swimmers
Q kHhU.l:?A0Vector v=swimmers.getList(false);51Testing软件测试网C(HOr6Ah
loadList(v);
:?5_(Xc'_.u7Uq0}51Testing软件测试网Wx*RI}+Y
51Testing软件测试网Q8~3_(B3g
尽管这个方法在简单、小型的情况下工作得很好,但是它没有良好的可扩展性。如果你有10个按钮,扩展actionPerformed()方法来测试每个按钮和调用某些对应的操作,会使得可读性非常差。相反,我们最好在包含用户接口的类中去掉所有的判定。51Testing软件测试网 A&J8hwE%]
51Testing软件测试网$t zQP1J做到这点的一个途径是使用Command模式。当我们使用这个模式的时候,需要我们创立一个Command接口:
h@zh"u4\'_Q,N051Testing软件测试网lo3ZlAH`3u P!JH@;X0//the Command interface d `+j%`n]d/O0public interface Command{ 8d)Q1H(fi ?k%XA$S0public void execute(); a Y Z~h:RL0} |
k?*a-a*H ~"to9k0 我们将三个单选按钮扩展成特定的带有Command接口的类,我们就可以把对命令的执行从JFrame类转移到每个按钮的类。同时,我们创建一 个叫做SexButton的基类,并将ActionListener代码移到基类中,这样就不需要分别在每个按钮中添加事件监听器:
`z6J CD8D!p051Testing软件测试网v3Ey$G2K|q!lyk ILhG1@:W&~0//abstract radio button class51Testing软件测试网5^tW|5] public abstract class SexButton P^%|X[X-Y0extends JRadioButton implements Command{51Testing软件测试网m-{m`8F^U \s protected Swimmers simmers; &`BHp3@([0//JawList is a subclass of JScrollPane contained a JList;51Testing软件测试网#OMP'ItGx6f&T M protected JawList kidList; 9@7L#A9e@Sz0public SexButton(String title,Swimmers sw, /XN7e m:S0JawList klist,ActionListener al){51Testing软件测试网VB-H2x'NQ)D-K super(title); m9gO j7G&Ks0swimmers=sw;51Testing软件测试网"H8Pyb9W D kidList=klist; 1@ \3K:F ap/T0addActionListener(al);51Testing软件测试网rGIB!|:] } 7H+~!Z [a P0//abstract execute method ,Y#b5f6gHf K0public abstract void execute(); O:S}h8X9V(kF0} |
V2Z*X3|+v0F:\"z0 注意这个类必须被扩展以使得它有用,因为我们没有具体化execute()方法。这个基本的抽象按钮类只是我们从中导出的具体类的一个模板,这实际也是模板设计模式的一个简单例子。
,C#x:x ?)~[0