和风细雨

世上本无难事,心以为难,斯乃真难。苟不存一难之见于心,则运用之术自出。

一个解析文本中的信息并向对象赋值过程的思考.

首先解释一下,文本中的信息指的是 对象在文本文件中的描述,如"名称:Bill 职位:SSE 年龄:45  薪水:10000"这个形式的.要求把这样的信息转换到对象Member中,对录入出错的情况如年龄薪水有非数字字符需要加以鉴别.

对象基本信息如下:

public class Member implements Comparable{
    
// 名称
    private String name;

    
// 年龄
    private int age;

    
// 职位
    private String title;

    
// 薪水
    private int salary;
    
    .    
    
}



从这段字符串中找到相关的信息并设置到Member对象的相关属性中并不难,但有几个地方需要多加考虑:
1.名称职位薪水年龄的顺序不一定一致.
2.职位薪水年龄三个字段和值有可能没有.
3.有可能需要增加字段,此时类也需要修改.

处理程序需要考虑解析,验证,赋值三个环节,如果耦合在一起处理当然也能做出来,但这样做可读性和可维护性都不好,也背离了面向对象的初衷.好的方案应该把这三部分分开制作函数处理.

文本解析部分:
我的想法是首先将"名称:Bill 职位:SSE 年龄:45  薪水:10000"以空格劈分成包含这样元素的链表:
名称:Bill
职位:SSE
年龄:45 
薪水:10000

然后在用冒号":"劈分单个元素,前半部分作为键,后半部分作为值,放入一个Hashtable中:
key    value
名称 Bill
职位 SSE
年龄 45 
薪水 10000

解析部分代码如下:

    /**
     * 将分段字符串链表转化成成员链表,不成功者记入错误链表
     * 
     * 
@param segmentList
     *            分段字符串链表
     
*/

    
private void changeSegmentToMember(List<String> segmentList) {
        
for (String segment : segmentList) {
            Map
<String, String> ht = StringUtil.parseStr2Map(segment, " "":");

            Member member 
= new Member();

            
if (member.setHtToProperties(ht)) {
                
// 成功赋值,将成员放入成员列表
                memberList.add(member);
            }
 else {
                
// 有任何错误,将分段信息放入错误链表
                errorList.add(segment);
            }

        }

    }



赋值和验证部分:
然后把这个Hashtable传入到Member的一个函数setHtToProperties中,这个函数的任务是对Hashtable中的键值对进行遍历,在调用函数setValueToProperty对字段进行赋值:

代码如下:

    /**
     * 将哈息表中成对的值按规则输入属性
     * 
@param ht
     * 
@return
     
*/

    
public boolean setHtToProperties(Map<String,String> ht){
        Iterator it
=ht.keySet().iterator();
        
        
while(it.hasNext()){
            String key
=(String)it.next();
            String value
=(String)ht.get(key);
            
            
boolean isSettted=setValueToProperty(key,value);
            
            
if(isSettted==false){
                
return false;
            }

        }

        
        
return true;
    }

    
    
/**
     * 在mapping关系中用属性名去找属性对应的变量,是则赋值;如找不到或转化出错则返回假
     * 
@param propertyName 属性名,如name对应的名称
     * 
@param propertyNalue 属性值,如那么对应的Bill
     * 
@return
     
*/

    
private boolean setValueToProperty(String propertyName,String propertyNalue){
        
if(propertyName.equals("名称")){
            name
=propertyNalue;
        }

        
else if(propertyName.equals("年龄")){
            
try{
                
int ageTemp=Integer.parseInt(propertyNalue);
                age
=ageTemp;
            }

            
catch(Exception e){
                
return false;
            }
            
        }

        
else if(propertyName.equals("职位")){
            title
=propertyNalue;
        }

        
else if(propertyName.equals("薪水")){
            
try{
                
int salaryTemp=Integer.parseInt(propertyNalue);
                salary
=salaryTemp;
            }

            
catch(Exception e){
                
return false;
            }

        }

        
else{
            
return false;
        }


        
return true;
    }


建立setValueToProperty函数的初衷是,用分支语句建立起键值与字段的对应关系,对应上了则进行赋值,这和Mapping有点类似,有些转化和验证工作也在分支内进行,只要验证出现问题即退出处理.

这样的处理方法带来了如下好处:
1.外界的类只需要解析文本,不需也不应该知道如何向Member的对应字段赋值,这个工作应该由Member自己进行,setHtToProperties函数帮助达成了这一点,有效降低了Member和其它类的耦合程度.
2.即使职位薪水年龄三个字段和值缺失,也不影响其它字段的赋值过程.
3.如果增加字段,setValueToProperty函数中只需要增加一个Mapping分支即可,其它地方无须改动.
4.对数据的校验工作可以统一在setValueToProperty函数中完成.

进行了如此处理后,代码量也不见得比混合处理多多少,而程序更加清晰,适应性也增强了,经得起不断更改. 比解析验证赋值混合在一起的方案要强的多.

完整代码下载:
http://www.blogjava.net/Files/sitinspring/MemberProcessor20071207163615.rar

posted on 2008-02-22 10:28 和风细雨 阅读(148) 评论(0)  编辑  收藏


只有注册用户登录后才能发表评论。


网站导航: