写代码 重构 写代码 重构 进步

简单的题目 不简单的问题!

题目:假设每个学生有3门课的成绩,从键盘接收用户的输入(要求用户按照一种良好的格式依次输入5名学生的姓名和成绩),在程序中按总分数从高到低的顺序将这5名学生信息按照一种良好的格式存放在“stu.txt”文件中

这样一个程序 如果只是实现功能对一个coder来说应该再简单不过了,几个方法搞定,却不知灾难将至。

 

 

代码
//真对排序算法的变动 应该抽象父类 
class ClassSort<E>{
    private TreeSet<E> set = null;
    
private static ClassSort sort = new ClassSort();
    
private ClassSort(){}
    
public static ClassSort getInstence(){
        
return sort;
    }
//end method
    public TreeSet<E> getSet(Comparator<? super E> compartor){           
     
if(set == null)
            set 
= new TreeSet<E>(compartor);
        
return set;
    }
//end method 
}//end class SortClass 

class WriteNative<T>{
    
private BufferedWriter bw = null;
    
private TreeSet<T> set = null;
    
public WriteNative(TreeSet<T> set){
            
this.set = set;
    }
    
public void Write() throws IOException{
        File path 
= new File("D:\\MyTestWrite3.txt");
        
if(!path.exists())
            path.createNewFile();
        Write(path);
    }
    
public void Write(File path) throws IOException{
        
if(path == null)
            
return;
        
if(bw == null)
            bw 
= new BufferedWriter(new FileWriter(path,true));
        
if(set.size() != 0){
            
for(T t : set)    
                bw.write(t
+"\r\n");
        }
        bw.close();
    }
//end method 
}//end class WriteNative


interface IClientProgram{
    
void writeIn(String info);
    
void writeNative();
}

//这个类应该依赖于抽象 而不应该依赖于具体实现  算法的变动会给这个类带来毁灭性的灾难 鸡肋代码就在这里 让我们去重构它吧
//怎么重构才会改善这种高耦合性的代码带来的灾难呢 这就是问题所在!
class Client implements IClientProgram{
    
//在构造函数中组合具体子类 现在还没有抽象出父类 所以先依赖具体实现吧! 等待重构
    private WriteNative writeNative = null;
    
private ClassSort sort = null;
    String [] strs 
= new String[3];
    TreeSet
<Student> set = null;
    
public void writeIn(String info){
        split(info);
//分解
        sort = ClassSort.getInstence();
        set 
= sort.getSet(new Comparator<Student>(){
            
public int compare(Student stu1, Student stu2) {
                
long firstCompartor = stu1.getSum() - stu2.getSum();
                
if(firstCompartor == 0)
                    
return stu1.getName().compareTo(stu2.getName());
                
return (int)firstCompartor;
            }
        });
//end anonymous innerclass
        
        
long english = Long.parseLong(strs[1]);
        
long math = Long.parseLong(strs[2]);
        set.add(
new Student(strs[0],(english + math)));
        
    }
//end method writenIn
    public void writeNative(){
        
if(set == null)return;
        writeNative 
= new WriteNative(set);
        
try {
            writeNative.Write();
        } 
catch (IOException e) {
            
// TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
private void split(String info){
        
if(info != null){
            
for(int i=0; i<3; i++){
                strs[i] 
= info.split(" ")[i];
            }
//end for
        }//end if
    }//end method split
  
}
//end class Client
class Student{
    
private String name;
    
private long sum;
    
public Student(String name,long sum){
        
this.name = name;
        
this.sum = sum;
    }
//end constructor
    public String getName(){
        
return this.name;
    }
    
public long getSum(){
        
return this.sum;
    }
    
public String toString(){
        
return name +":"+ sum;
    }
//end method 
}//end innerclass 

 

上面的代码 已经实现了题目中要求完成的功能 同时代码中也提出了一些需要重构的地方 考虑一下如果需求真的变动了 要求用自然顺序去写入文件这段代码要改动的地方是不是毁灭性的改动 那么我们如何去避免能够预测的改动带来的风险呢?

下面是这段代码的main函数调用

 

代码
public static void main(String[] args){
     System.out.println("请输入信息按照:姓名(空格)英语成绩(空格)数学成绩(空格) 换行输入bye结束输入");
        BufferedReader br 
= new BufferedReader(new InputStreamReader(System.in));
        IClientProgram cli 
= new Client();
        String info ;
        
boolean b = true;
        
while(b){
            
try {
                info 
= br.readLine();
                
if("bye".equals(info))
                    
break;
                cli.writeIn(info);
            } 
catch (IOException e) {
                
// TODO Auto-generated catch block
                e.printStackTrace();
            }
//end catch
        }//end while
        cli.writeNative();
    }
//end method main 

 

客户端做到了与逻辑相分离,只是调用实现 

接下来要做的就是总结问题 重构代码了 继续

posted @ 2009-12-17 22:29  小喆  阅读(425)  评论(2)    收藏  举报