That way I want to stay

BlogJava 首页 新随笔 联系 聚合 管理
  55 Posts :: 1 Stories :: 41 Comments :: 0 Trackbacks

下载地址 


http://www.blogjava.net/Files/Wingel/第5章慎用继承.rar

http://wingel.javaeye.com/topics/download/81eb4c8a-e19f-48a3-bcf9-1256053a1d79

下面是摘录的片段:


第5章 慎用继承

示例

  这是一个会议管理系统。用来管理各种各样的会议参与者信息。数据库里面有个表Participants,里面的每条记录表示一个参会者。因为经常会发生用户误删掉某个参会者的信息。所以现在,用户删除时,并不会真的删除那参会者的信息,而只是将该记录的删除标记设为true。24小时以后,系统会自动将这条记录删除。但是在这24小时以内,如果用户改变主意了,系统还可以将这条记录还原,将删除标记设置为false。

  请认真的读下面的代码:

    public class DBTable {                                                                        
       protected Connection conn;                                                                 
       protected tableName;                                                                       
       public DBTable(String tableName) {                                                         
           this.tableName = tableName;                                                            
           this.conn = ...;                                                                       
       }                                                                                          
       public void clear() {                                                                      
           PreparedStatement st = conn.prepareStatement("DELETE FROM "+tableName);                
           try {                                                                                  
               st.executeUpdate();                                                                
           }finally{                                                                              
               st.close();                                                                        
           }                                                                                      
       }                                                                                          
       public int getCount() {                                                                    
           PreparedStatement st = conn.prepareStatement("SELECT COUNT(*) FROM"+tableName);                                                                                 
           try {                                                                                  
               ResultSet rs = st.executeQuery();                                                  
               rs.next();                                                                         
               return rs.getInt(1);                                                               
           }finally{                                                                              
               st.close();                                                                        
           }                                                                                      
       }                                                                                          
    }                              
   
    public class ParticipantsInDB extends DBTable {                                               
       public ParticipantsInDB() {                                                                
           super("participants");                                                                 
       }                                                                                          
       public void addParticipant(Participant part) {                                             
           ...                                                                                    
       }                                                                                          

       public void deleteParticipant(String participantId) {
           setDeleteFlag(participantId, true);
       }                     
       public void restoreParticipant(String participantId) {
           setDeleteFlag(participantId, false);
       }                     
       private void setDeleteFlag(String participantId, boolean b) {
           ...               
       }                     
       public void reallyDelete() {
           PreparedStatement st = conn.prepareStatement(
                             "DELETE FROM "+
                             tableName+
                             " WHERE deleteFlag=true");
           try {             
               st.executeUpdate();
           }finally{         
               st.close();   
           }                 
       }                     
       public int countParticipants() {
           PreparedStatement st = conn.prepareStatement(
                             "SELECT COUNT(*) FROM "+
                             tableName+
                             " WHERE deleteFlag=false");
           try {             
               ResultSet rs = st.executeQuery();
               rs.next();    
               return rs.getInt(1);
           }finally{         
               st.close();   
           }                 
       }                     
    }                        

  注意到,countParticipants这个方法只计算那些deleteFlags为false的记录。也就是,被删除的那些参会者不被计算在内。

  上面的代码看起来还不错,但却有一个很严重的问题。什么问题?先看看下面的代码:

    ParticipantsInDB partsInDB = ...;
    Participant kent = new Participant(...);
    Participant paul = new Participant(...);
    partsInDB.clear();       
    partsInDB.addParticipant(kent);
    partsInDB.addParticipant(paul);
    partsInDB.deleteParticipant(kent.getId());
    System.out.println("There are "+partsInDB.getCount()+ "participants");

  最后一行代码,会打印出"There are 1 participants"这样信息,对不?错!它打印的是"There are 2 participants"!因为最后一行调用的是DBTable里面的这个方法getCount,而不是ParticipantsInDB的countParticipants。getCount一点都不知道删除标记这回事,它只是简单的计算记录数量,并不知道要计算那些真正有效的参会者(就是删除标记为false的)。


继承了一些不合适(或者没用的)的功能

具体的内容在上面的下载链接里面的pdf文件里,看pdf比较舒服。

posted on 2006-11-29 20:40 Wingel 阅读(1201) 评论(3)  编辑  收藏 所属分类: 敏捷开发

Feedback

# re: (原创翻译) 敏捷开发的必要技巧5:慎用继承 2006-11-30 12:52 Dustin Tang[匿名]
观点是对的, 例子就没有举到点子上.  回复  更多评论
  

# re: (原创翻译) 敏捷开发的必要技巧5:慎用继承 2006-11-30 16:40 someone
继承没有借口干净,但是也不是什么时候都不如接口。
这个例子没有说明什么问题,如果父类里面getCount方法并不实现,abstact或者抛异常的,强制在子类实现,就是非常合适的用法。  回复  更多评论
  

# re: (原创翻译) 敏捷开发的必要技巧5:慎用继承 2006-12-01 09:14 Wingel
我这章的观点并不是表达继承不好,我的意思是说,要谨慎的使用继承。如果将这个方法定义成abstract的话,那就不叫继承自这个方法,而应该叫实现这个方法了。如果父类中不实现这个方法绝对是恶心的代码,抛异常的话,那你就必须有足够的testcase来保证逻辑的准备。  回复  更多评论
  


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


网站导航: