为你的程序锦上添花的五种程序组织形式

形式一."见兔撒鹰".

如果有一个类有一个集合成员,可以在为此成员添加元素时再把具体集合建立起来,以免浪费空间和时间.

例:

1publicclass Company{
2privateListmembers=null
;
3

4publicvoid addMember(Membermember){
5if(members=null
){
6members=new
ArrayList();
7
}
8

9 members.add(member);
10
}
11
}
12

异曲同工的另外一个例子:

1publicclass Singleton{
2privatestaticSingletoninstance=null
;
3

4publicstaticsynchronized SingletongetInstance(){
5//要用的时候再把Singleton建立起来

6if(instance==null ){
7instance=new
Singleton();
8
}
9

10return instance;
11
}
12
}
13

形式二."只管结果,不顾过程"

从集合中取区间元素时,可以直接从上下限之间取来,让try...catch...去处理越界的事.

题设:有个数不定元素的列表(allTodoes),需要从中取N个,起始位置不限,你怎么编写程序.

很多人开始进行越界的判断,出来一堆if else,有时还需要在纸上写好思路,完毕后还有多方测试,生怕出错,即使编写好后其他人维护起来也是小心翼翼的.其实没必要这么麻烦.

例.

1intstart=pageIndex* pageSize;
2intend=start+
pageSize;
3

4for(inti=start;i<end;i++
){
5try
{
6
todoResult.addTodo((Todo)allTodoes.get(i));
7
}
8catch
(Exceptionex){
9continue
;
10
}
11}

题外话:分支和循环语句天生就不容易理解,尤其是在嵌套较深的时候,因为这是机器的思维特性.还是try...catch...比较贴近人类思维.


形式三."奉旨行事"
在查询中,如果把查询条件和遴选过程分开来更有益,程序也因此解耦合.这才是OO化的查询.

需求:从公司的职员列表中,找出男性且年龄大于22的成员.

传统写法:

1Listallmembers=company.getMembers();//取得所有成员
2Listresults=newArrayList();//结果列表
3
4for(Iteratorit=
allmembers.iterator();it.hasNext();){
5Membermember=
(Member)it.next();
6

7if(member.getAge()>22&&member.isMale()){//筛选,这里是把查询条件和遴选过程融合在一起,条件一变立即就得加个分支.

8 results.add(member);
9
}
10
}
11

这种写法没有错,但是不是面向对象的写法,它有以下缺陷:
1.查询条件和筛选过程没有分离.
2.这样写的后果使Company变成了一个失血模型而不是领域模型.
3.换查询条件的话,上面除了"筛选"一句有变化外其它都是模板代码,重复性很高.

真正符合OO的查询应该是这样:

1MemberFilterfilter1=new MemberFilter(){
2publicboolean
accept(Membermember){
3returnmember.isMale()&&member.getAge()>22
;
4
}
5
};
6

7Listls=company.listMembers(filter1);

这段代码成功的把查询条件作为一个接口分离了出去,接口代码如下:

1publicinterface MemberFilter{
2publicboolean
accept(Membermember);
3}

而类Company增加了这样一个函数:

1public ListlistMembers(MemberFiltermemberFilter){
2Listretval=new
ArrayList();
3

4for(Iteratorit=
members.iterator();it.hasNext();){
5Membermember=
(Member)it.next();
6

7if
(memberFilter.accept(member)){
8
retval.add(member);
9
}
10
}
11

12return
retval;
13}

这就把模板代码归结到了类内部,外面不会重复书写了.Company也同时拥有了数据和行为,而不是原来的数据容器了.

形式四."化繁为简"
这种结构将多个分支语句变换为一个查表结构,这样做对扩充程序结构,修改具体数额都很方便,使程序更易于维护.还可以把归结出的表结构放在持久介质中如XML文件,数据库等,用到的时候再取,这样做在条件变化时不需要修改程序.

原始代码(VB代码,但应该不妨碍理解):

1Dim count1
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

变换如下:
这是个税率计算的语句段,公式是确定的:税=月薪*税率-折扣,税率又和月薪有关系,月薪越高税率越高,首先这里可以归纳出一个基本类:

1publicclass TaxItem{
2floatlimit;//月薪界限

3floatratio;//税率
4floatdiscount;//折扣
5
6publicTaxItem(floatlimit,floatratio,float discount){
7this.limit=
limit;
8this.ratio=
ratio;
9this.discount=
discount;
10
}
11

12public TaxItem(){
13this(0.0f,0.0f,0.0f
);
14
}
15

16publicfloat getDiscount(){
17return
discount;
18
}
19

20publicfloat getLimit(){
21return
limit;
22
}
23

24publicfloat getRatio(){
25return
ratio;
26
}
27
}
28

29


然后就是税计算类:

1publicclass TaxCaculator{
2privatestaticArrayListlist=new
ArrayList();
3

4public
TaxCaculator(){
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(float salary){
16TaxItemitem=new
TaxItem();
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=new TaxCaculator();
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));


形式五."分而治之"
该结构将分支语句的执行部分分散到单独的类中处理,降低了系统耦合度,程序也更容易维护.

举例如下:
在日常工作中,我们经常需要解析一段字符串并交由相应的函数进行处理,例如TCP/IP通信中的命令解析和用户自定义文件解析等场合,通常的处理方法是这样:

if(命令==”AAA”){
函数AAA执行;
}
else if(命令==”BBB”){
函数BBB执行;
}
.
.
.
else{
函数XXX执行;
}

这种方法在命令较少时是有效的,当命令众多时,if语句和相关的函数将会形成一个巨集,给检查,维护和扩充带来了很大的不便,久而久之将会成为系统性能提升的瓶颈。

一个成功的软件程序必须尽可能简单并易于重构和扩展,在命令模式和Java反射机制的帮助下,我们可以从容解决上述问题,达到简单并易于重构和扩展的要求。以下将简要说明解决方案。

1. 制作一个命令的抽象接口.

1publicinterface Command{
2publicabstractvoid
execute(String[]args);
3}

2. 让每种命令都实现这个接口.

1//命令一
2publicclassCommandType01implements Command{
3publicvoid
execute(String[]args){
4System.out.println("\ncommandType01start!"
);
5System.out.print("\tcommandType01Length="+
args.length);
6System.out.println("\ncommandType01End!"
);
7
}
8
}
9

10//命令二
11publicclassCommandType02implements Command{
12publicvoid
execute(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//命令三
25publicclassCommandType03implements Command{
26publicvoid
execute(String[]args){
27System.out.println("\ncommandType03start!"
);
28System.out.print("\tcommandType03lastNation="+args[args.length-1
]);
29System.out.println("\ncommandType03End!"
);
30
}
31
}
32

33


让每种命令都实现execute接口的用意是强制每个命令的执行方式一致,简化调用时的处理,但执行内容应该根据实际情况决定.
例如
命令一的执行内容是输出参数的个数
命令二的执行内容是输出参数的内容
命令三的执行内容是输出最后一个参数

3. 将命令防置到命令中心中去
命令中心类的代码如下:

1publicclass Mediation{
2Commandcmmd;//命令对象的引用

3String[]cmmdArgs;//参数列表
4
5public
Mediation(){
6

7
}
8

9publicvoid
fetchCommand(StringstrCmmd){
10cmmdArgs=strCmmd.split("\s+");//分析原始命令

11
12StringclassName="Command"+cmmdArgs[0];//根据分析后命令的第一个参数得到类名

13
14try
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值