http://www.aygfsteel.com/Files/Wingel/第5章慎用繼承.rar
http://wingel.javaeye.com/topics/download/81eb4c8a-e19f-48a3-bcf9-1256053a1d79
下面是摘錄的片段:
第5章 慎用繼承
示例
這是一個(gè)會(huì)議管理系統(tǒng)。用來管理各種各樣的會(huì)議參與者信息。數(shù)據(jù)庫(kù)里面有個(gè)表Participants,里面的每條記錄表示一個(gè)參會(huì)者。因?yàn)榻?jīng)常會(huì)發(fā)生用戶誤刪掉某個(gè)參會(huì)者的信息。所以現(xiàn)在,用戶刪除時(shí),并不會(huì)真的刪除那參會(huì)者的信息,而只是將該記錄的刪除標(biāo)記設(shè)為true。24小時(shí)以后,系統(tǒng)會(huì)自動(dòng)將這條記錄刪除。但是在這24小時(shí)以內(nèi),如果用戶改變主意了,系統(tǒng)還可以將這條記錄還原,將刪除標(biāo)記設(shè)置為false。
請(qǐng)認(rèn)真的讀下面的代碼:
??? 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這個(gè)方法只計(jì)算那些deleteFlags為false的記錄。也就是,被刪除的那些參會(huì)者不被計(jì)算在內(nèi)。
上面的代碼看起來還不錯(cuò),但卻有一個(gè)很嚴(yán)重的問題。什么問題?先看看下面的代碼:
??? 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");
最后一行代碼,會(huì)打印出"There are 1 participants"這樣信息,對(duì)不?錯(cuò)!它打印的是"There are 2 participants"!因?yàn)樽詈笠恍姓{(diào)用的是DBTable里面的這個(gè)方法getCount,而不是ParticipantsInDB的countParticipants。getCount一點(diǎn)都不知道刪除標(biāo)記這回事,它只是簡(jiǎn)單的計(jì)算記錄數(shù)量,并不知道要計(jì)算那些真正有效的參會(huì)者(就是刪除標(biāo)記為false的)。
繼承了一些不合適(或者沒用的)的功能
具體的內(nèi)容在上面的下載鏈接里面的pdf文件里,看pdf比較舒服。