形式一."见兔撒鹰". 例:
1publicclassCompany{
2privateListmembers=null; 3 4publicvoidaddMember(Membermember){ 5if(members=null){ 6members=newArrayList(); 7} 8 9members.add(member); 10} 11} 12 | |
异曲同工的另外一个例子:
1publicclassSingleton{
2privatestaticSingletoninstance=null; 3 4publicstaticsynchronizedSingletongetInstance(){ 5//要用的时候再把Singleton建立起来 6if(instance==null){ 7instance=newSingleton(); 8} 9 10returninstance; 11} 12} 13 形式二."只管结果,不顾过程" 题设:有个数不定元素的列表(allTodoes),需要从中取N个,起始位置不限,你怎么编写程序. 很多人开始进行越界的判断,出来一堆if else,有时还需要在纸上写好思路,完毕后还有多方测试,生怕出错,即使编写好后其他人维护起来也是小心翼翼的.其实没必要这么麻烦. 例.
1intstart=pageIndex*pageSize;
2intend=start+pageSize; 3 4for(inti=start;i<end;i++){ 5try{ 6todoResult.addTodo((Todo)allTodoes.get(i)); 7} 8catch(Exceptionex){ 9continue; 10} 11} 题外话:分支和循环语句天生就不容易理解,尤其是在嵌套较深的时候,因为这是机器的思维特性.还是try...catch...比较贴近人类思维.
需求:从公司的职员列表中,找出男性且年龄大于22的成员. 传统写法:
1Listallmembers=company.getMembers();//取得所有成员
2Listresults=newArrayList();//结果列表 3 4for(Iteratorit=allmembers.iterator();it.hasNext();){ 5Membermember=(Member)it.next(); 6 7if(member.getAge()>22&&member.isMale()){//筛选,这里是把查询条件和遴选过程融合在一起,条件一变立即就得加个分支. 8results.add(member); 9} 10} 11 这种写法没有错,但是不是面向对象的写法,它有以下缺陷: 真正符合OO的查询应该是这样:
1MemberFilterfilter1=newMemberFilter(){
2publicbooleanaccept(Membermember){ 3returnmember.isMale()&&member.getAge()>22; 4} 5}; 6 7Listls=company.listMembers(filter1); 这段代码成功的把查询条件作为一个接口分离了出去,接口代码如下:
1publicinterfaceMemberFilter{
2publicbooleanaccept(Membermember); 3} 而类Company增加了这样一个函数:
1publicListlistMembers(MemberFiltermemberFilter){
2Listretval=newArrayList(); 3 4for(Iteratorit=members.iterator();it.hasNext();){ 5Membermember=(Member)it.next(); 6 7if(memberFilter.accept(member)){ 8retval.add(member); 9} 10} 11 12returnretval; 13} 这就把模板代码归结到了类内部,外面不会重复书写了.Company也同时拥有了数据和行为,而不是原来的数据容器了. 形式四."化繁为简" 原始代码(VB代码,但应该不妨碍理解):
1Dimcount1
2count1=salary.Value+USA.Value*Drate+JAN.Value*Jrate-4000 3Ifcount1<500Then 4tax.Value=count1*0.05 5ElseIfcount1<2000Then 6tax.Value=count1*0.1-25 7ElseIfcount1<5000Then 8tax.Value=count1*0.15-125 9ElseIfcount1<20000Then 10tax.Value=count1*0.2-375 11ElseIfcount1<40000Then 12tax.Value=count1*0.25-1375 13ElseIfcount1<60000Then 14tax.Value=count1*0.3-3375 15Else 16tax.Value=count1*0.3-3375 17EndIf 变换如下:
1publicclassTaxItem{
2floatlimit;//月薪界限 3floatratio;//税率 4floatdiscount;//折扣 5 6publicTaxItem(floatlimit,floatratio,floatdiscount){ 7this.limit=limit; 8this.ratio=ratio; 9this.discount=discount; 10} 11 12publicTaxItem(){ 13this(0.0f,0.0f,0.0f); 14} 15 16publicfloatgetDiscount(){ 17returndiscount; 18} 19 20publicfloatgetLimit(){ 21returnlimit; 22} 23 24publicfloatgetRatio(){ 25returnratio; 26} 27} 28 29
1publicclassTaxCaculator{
2privatestaticArrayListlist=newArrayList(); 3 4publicTaxCaculator(){ 5//这里把各个等级加入到链表中,注意添加顺序是由小到大 6list.add(newTaxItem(500.0f,0.05f,0.0f)); 7list.add(newTaxItem(2000.0f,0.1f,25.0f)); 8list.add(newTaxItem(5000.0f,0.15f,125.0f)); 9list.add(newTaxItem(20000.0f,0.2f,375.0f)); 10list.add(newTaxItem(40000.0f,0.25f,1375.0f)); 11list.add(newTaxItem(60000.0f,0.3f,3375.0f)); 12} 13 14//这个函数用来计算所得税 15publicfloatgetTax(floatsalary){ 16TaxItemitem=newTaxItem(); 17 18for(inti=0;i<list.size();i++){ 19item=(TaxItem)list.get(i); 20 21if(salary>item.getLimit()){ 22continue; 23} 24else{ 25break; 26} 27} 28 29//返回最终结果,当然,这个公式也可以放在TaxItem类中,这里就见仁见智了。 30returnsalary*item.getRatio()-item.getDiscount(); 31} 32}
1TaxCaculatortaxCaculator=newTaxCaculator();
2 3floatsalary=1000.f; 4System.out.println("Salary="+salary+"Tax="+taxCaculator.getTax(salary)); 5 6salary=2000.f; 7System.out.println("Salary="+salary+"Tax="+taxCaculator.getTax(salary)); 8 9salary=3000.f; 10System.out.println("Salary="+salary+"Tax="+taxCaculator.getTax(salary));
举例如下: if(命令==”AAA”){ 这种方法在命令较少时是有效的,当命令众多时,if语句和相关的函数将会形成一个巨集,给检查,维护和扩充带来了很大的不便,久而久之将会成为系统性能提升的瓶颈。 一个成功的软件程序必须尽可能简单并易于重构和扩展,在命令模式和Java反射机制的帮助下,我们可以从容解决上述问题,达到简单并易于重构和扩展的要求。以下将简要说明解决方案。 1. 制作一个命令的抽象接口.
1publicinterfaceCommand{
2publicabstractvoidexecute(String[]args); 3} 2. 让每种命令都实现这个接口.
1//命令一
2publicclassCommandType01implementsCommand{ 3publicvoidexecute(String[]args){ 4System.out.println("\ncommandType01start!"); 5System.out.print("\tcommandType01Length="+args.length); 6System.out.println("\ncommandType01End!"); 7} 8} 9 10//命令二 11publicclassCommandType02implementsCommand{ 12publicvoidexecute(String[]args){ 13System.out.println("\ncommandType02start!"); 14 15System.out.print("\tcommandType02is:"); 16for(Stringitem:args){ 17System.out.print("\t"+item); 18} 19 20System.out.println("\ncommandType02End!"); 21} 22} 23 24//命令三 25publicclassCommandType03implementsCommand{ 26publicvoidexecute(String[]args){ 27System.out.println("\ncommandType03start!"); 28System.out.print("\tcommandType03lastNation="+args[args.length-1]); 29System.out.println("\ncommandType03End!"); 30} 31} 32 33
3. 将命令防置到命令中心中去
1publicclassMediation{ 2Commandcmmd;//命令对象的引用 3String[]cmmdArgs;//参数列表 4 5publicMediation(){ 6 7} 8 9publicvoidfetchCommand(StringstrCmmd){ 10cmmdArgs=strCmmd.split("\s+");//分析原始命令 11 12StringclassName="Command"+cmmdArgs[0];//根据分析后命令的第一个参数得到类名 13 14try |