下載地址
http://m.tkk7.com/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比較舒服。