懶對象加載模式

 
問題
隨着輕量級持久化框架的流行(如:Hibernate,JDO,JPA),領域對象取代了傳統的DTO直接作爲值對象,而在這種架構應用的開發過程中,開發人員常會遇見這樣的異常LazyInitializationException。上述問題是由於Hibernate對於領域對象的關係域對象採取了懶加載策略所導致的(即在關係域被訪問時才真正加載創建這些相關對象,Hibernate提供的懶加載策略在很多時候都可以讓我的程序獲得更高的效率);由於領域對象在脫管的狀態下被作爲值對象傳回顯示層,而顯示層如果訪問了採用懶加載策略加載的關係域,便會導致LazyInitializationException異常。
爲了避免這個問題,我們常常會在Façade層的業務方法中加入與特定顯示要求相綁定的返回對象初始化過程(即裝載那些被懶加載了的關係域對象)。Façade通常是我們用於控制事務邊界和完成返回的領域對象脫鉤的地方。
1 表現層是易變的這樣就會導致連鎖反應,大量的代碼需要維護,完全違背了面向對象設計的原則,增加了程序的維護成本。
2 並且Façade可能用於支持多種不同的表現層,很難讓一個方法滿足不同的要求。
OSIV(Open Session in View)結構是一種解決上述問題的方法,這種結構之所以能解決上述問題關鍵就在於OSIV在表現層中控制Session的打開和關閉,控制事務邊界。OSIV雖然簡化了應用程序的結構,也避免了LazyInitializationException問題,但是也有很多不足:1.增加了表示層的負責度,2.在響應返回表示層前必須提交事務。3.由於減少了封裝層次,表現層直接操作領域對象使得包括性能方面的各種優化更爲困難。
解決方案
思考既然表示層知道要顯示的信息,即領域對象應該加載哪些相關聯的對象。那麼我們何不把這個任務交給Façade的調用者(表現層)來完成呢?
不同的表示層可能會有不同的顯示策略,利用策略模式(GoF)我們讓表示層來注入所需的關係域加載策略實現。
下面便是這個想法的實現:
示例中的領域模型:

 

圖表 1 示例中領域對象模型
 
示例中相關的組件

圖表 2 示例相關組件
LazyObjectLoader:懶對象加載者接口,其定義如下
來對象加載策略接口
package org.ccsoft;
 
publicinterface LazyObjectLoader {
    publicvoid loadLazyObjects(Object obj);
}
該接口定義了不同懶對象加載策略實現者要實現的方法,在loadLazyObjects方法中實現對領域對象obj相關的關係域對象進行加載的策略。
OrderItemLoader一種加載策略的實現,用於加載Order對象的關係域對象OrderItem對象
package org.ccsoft;
 
import java.io.Serializable;
 
publicclass OrderItem implements Serializable {
   
    private String detail;
    public String getDetail() {
       returndetail;
    }
    publicvoid setDetail(String detail) {
       this.detail = detail;
    }
   
}
OrderMgrFacadeImp: Façade的實現,可以使POJO也可以使Session Bean
 
package org.ccsoft;
 
publicclass OrderMgrFacadeImp implements OrderMgrFacade {
    private OrderDAO orderDAO;
    public OrderDAO getOrderDAO() {
       returnorderDAO;
    }
    publicvoid setOrderDAO(OrderDAO orderDAO) {
       this.orderDAO = orderDAO;
    }
    public Order getOrder(int orderId, LazyObjectLoader loader) {
       Order order=orderDAO.getOrder(orderId);
       loader.loadLazyObjects(order);
       return order;
    }
   
}
在getOrder方法中我們要求調用者提供了懶對象裝載策略的實例用於裝載那些調用者要用到的關係域對象。注意該示例是通過spring實現的,利用spring AOP完成事務管理,事務的邊界在Façade中方法上,當方法執行結束,事務業務將結束,並且Hibernate會自動關閉session,我們看到getOrder方法中在事務結束前調用了懶對象裝載策略,從而按照調用者的要求裝載了調用者所需的關係域對象。
該模式的優點
1 將領域對象的處理邏輯與顯示層的顯示邏輯完全分離,提高了代碼的可維護性和可擴展性
該模式的不足
1 要求顯示層的開發者,瞭解懶加載的情況
2 增加了代碼的複雜性

 ————————————————————————————————————


SCEA SCBCD MCSD
IBM Certified Specialist RUP
IBM Certified Solution Designer OOA&D UML v2
北京天融信軟件架構師
SUN,Microsoft培訓中心特邀高端教師
常年提供架構諮詢服務
[email protected] 010-82776427

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章