您的位置: 旅游网 > 影视

敏捷开发的必要技巧:慎用继承(1)

发布时间:2019-09-12 18:40:28

示例

这是一个会议管理系统。用来管理各种各样的会议参与者信息。数据库里面有个表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的)。

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

ParticipantsInDB继承了来自DBTable的方法,比如clear和getCount。对于ParticipantsInDB来讲,clear这个方法的确是有用的:清空所有的参会者。但getCount就造成了一点点小意外了:通过ParticipantsInDB调用getCount这个方法时,是取得participants这个表里面所有的记录,不管删除标记是true还是false的。而实际上,没人想知道这个数据。即使有人想知道,这个方法也不应该叫做getCount,因为这名字很容易就会跟“计算所有的(有效)参会者数量”联系在一起。

因此,ParticipantsInDB是不是真的应该继承这个方法getCount呢?或者我们应该怎么做比较恰当呢?

它们之间是否真的有继承关系?

当我们继承了一些我们不想要的东西,我们应该再三的想想:它们之间是不是真的有继承关系?ParticipantsInDB必须是一个DBTable吗?ParticipantsInDB希不希望别人知道它是一个DBTable?

实际上,ParticipantsInDB描述的是系统中所有的参会者的集合,该系统可以是个单数据库的,也可以是多数据库的,也就是说,这个类可以代表一个数据库里的一个Participants表,也可以代表两个数据库各自的两个Participants表的总和。

查看本文来源

宝宝咳嗽老不好
经常腹胀是什么原因
剖宫产术后腹胀怎么办
小孩消化不好怎么办
猜你会喜欢的
猜你会喜欢的