在介紹面向接口編程前,我們先來了解一下 IoC的基本原理,所謂 IoC,對于 Spring 框架來說,就是由 Spring 來負(fù)責(zé)控制對象的生命周期和對象間的關(guān)系。在一個對象中,如果要使用另外的對象,就必須得到它(自己 new 一個,或者從 JNDI 中查詢一個),使用完之后還要將對象銷毀(比如 Connection 等)。那么 IoC 是如何做的呢?Spring 所倡導(dǎo)的開發(fā)方式就是如此,所有的類都會在 Spring 容器中登記,告訴 Spring 你是個什 么東西,你需要什么東西,然后 Spring 會在系統(tǒng)運(yùn)行到適當(dāng)?shù)臅r候,把你要的東西主動給你,同時也把你交給其他需要你的東西。所有的類的創(chuàng)建、銷毀都由 Spring 來控制,也就是說控制對象生存周期的不再是引用它的對象,而是 Spring 。對于某個具體的對象而言,以前是它控制其他對象,現(xiàn)在是所有對象都被 Spring 控制,所以這叫控制反轉(zhuǎn)。
在應(yīng)用程序中,用來實(shí)現(xiàn)業(yè)務(wù)問題實(shí)體的(如,在電子商務(wù)應(yīng)用程序中的 Customer 和 Order)類就是持久化類。不能認(rèn)為所有的持久化類的實(shí)例都是持久的狀態(tài) —— 一個實(shí)例的狀態(tài)也可能是瞬時的或脫管的。
下面開始設(shè)計一個用戶持久化類,然后一步步學(xué)習(xí)如何利用 IoC 容器來處理用戶持久化類的。
首先,設(shè)計用戶持久化類的接口UserDao
,代碼如下:
public interface UserDao {
public void save(User user);
public User load(String name);
}
具體的持久化類必須要繼承UserDao
接口,并實(shí)現(xiàn)它的所有方法。我們還是首先實(shí)現(xiàn)內(nèi)存持久化的用戶類:
public class MemoryUserDao implements UserDao{
private static Map users = new HashMap();
static{
User user = new User("Moxie","pass");
users.put(user.getName(),user);
}
public void save(User user) {
users.put(user.getId(),user);
}
public User load(String name) {
return (User)users.get(name);
}
}
MemoryUserDao
的實(shí)現(xiàn)代碼和上面的MemoryUserPersist
基本相同,唯一區(qū)別是MemoryUserDao
類繼承了UserDao
接口,它的save()
和 load()
方法是實(shí)現(xiàn)接口的方法。
這時,客戶端UserRegister
的代碼又該如何實(shí)現(xiàn)呢?
UserDao userDao = new MemoryUserDao();
userDao.save(user);
注:面向?qū)ο蟆岸鄳B(tài)”的闡述
如果我們再切換到文本的持久化實(shí)現(xiàn)TextUserDao
,客戶端代碼仍然需要手工修改。雖然我們已經(jīng)使用了面向?qū)ο蟮亩鄳B(tài)技術(shù),對象 userDao
方法的執(zhí)行都是針對接口的調(diào)用,但 userDao
對象的創(chuàng)建卻依賴于具體的實(shí)現(xiàn)類,比如上面MemoryUserDao
。這樣我們并沒有完全實(shí)現(xiàn)前面所說的“ Client 不必知道其使用對象的具體所屬類”。
如何解決客戶端對象依賴具體實(shí)現(xiàn)類的問題呢?
下面該是我們的工廠(Factory)模式出場了!