淺析領域驅動模型VO、DTO、BO、PO 等的概念、區別及其用法


摘要:淺析POJO、DTO、DO、VO、BO、PO和Entity等的概念、區別及其用法。

名詞解釋

  領域模型中的實體類分為四種模型:VO、DTO、DO和PO,各種實體類用於不同業務層次間的交互,並會在層次內實現實體類之間的轉化。新項目使用了新的框架和開發規范,特意集體討論了DTO,DO,VO,BO,POJO,PO和Entity以及DAO、Model和View的基本概念和使用場景,為了深入理解,這里整理為一篇筆記。下面通過一張圖看一下它們的大致分類:
領域對象分類

  用MVC模式的角度接着看圖,看完圖估計大部分人對這些專業術語就有一個直觀的感受了:

POJO

  總的來說,普通Java對象POJO(Pure Old Java Object 、 Plain Ordinary Java Object),按照Martin Fowler的解釋是“Plain Old Java Object”,從字面上翻譯為“純潔老式的java對象”,但大家都使用“簡單java對象”來稱呼它。包含DO、DTO、BO、VO和PO等,它們本質上都是一個簡單的java對象,實際就是普通的JavaBeans。沒有業務邏輯,有時可以作為VO或DTO來使用。當然,這里特意說明純普通Java對象,如果你有一個簡單的運算屬性也是可以的,但不允許有業務方法。

  POJO是指這樣的java對象:

  • 有一些private的參數作為對象的屬性
  • 針對每一個參數定義get和set方法
  • 沒有從任何類繼承
  • 沒有實現任何接口
  • 沒有被其它框架侵入。

  許多開發者把JavaBean看作遵從特定命名約定的POJO。例如:

public class User {
    private Long id;
    private String userName;
    private String msg;
    private Integer age;
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
}

  POJO其實是比javabean更純凈的簡單類或接口。POJO嚴格地遵守簡單對象的概念,而不具有業務邏輯處理的能力,而一些JavaBean中往往會封裝一些簡單邏輯。例如,改造User后,可以得到一個JavaBean:

public class User implements Serializable {
    //實現serializable接口
    private static final long serialVersionUID = -2241142936329900646L;
    private Long id;
    private String userName;
    private String msg;
    private Integer age;
    /**
     * 無參構造器
     */
    public User() {
    }
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public User(Long id, String userName, Integer age) {
        this.id = id;
        this.userName = userName;
        this.age = age;
    }

}
VO

  VO(View Object)視圖模型,用於展示層,它的作用是把某個指定頁面(或組件)的所有數據封裝起來。如果是一個DTO對應一個VO,則DTO等價於VO;但是如果一個DTO對應多個VO,則展示層需要把VO轉換為服務層對應方法所要求的DTO,傳送給服務層,從而達到服務層與展示層解耦的效果。

  一般用在業務邏輯層(Service)對前端(Web) 的視圖模型效果控制的展示上,說白了就是后台向前端傳輸數據。示例:xxxVO,xxx一般為網頁名稱。注:在展示業務不復雜的系統,可直接使用DTO。

DTO

  數據傳輸對象DTO(Data Transfer Object)是一個比較特殊的對象,它有兩種存在形式:在后端,它的存在形式是java對象,也就是在controller里面定義的請求參數,通常在后端不需要關心怎么從json轉成java對象的,這個都是由一些成熟的框架幫你完成啦,比如spring框架;在前端,它的存在形式通常是js里面的對象(也可以簡單理解成json),即通過ajax請求的那個數據體。這也是為什么把他畫成橫跨兩層的原因。舉個例子,xxxDTO,xxx為業務領域相關的名稱。

  現在微服務盛行,服務和服務之間調用的傳輸對象能叫DTO嗎?我的理解是看情況,DTO的一個隱含意義是要能夠完整的表達一個業務模塊的輸出。如果服務和服務之間相對獨立,那就可以叫DTO;如果服務和服務之間不獨立,每個都不是一個完整的業務模塊,拆開可能僅僅是因為計算復雜度或者性能的問題,那這就不能夠叫做DTO,只能是BO。

  DTO與BO或者DO的區別是DTO沒有任何行為(方法),只是存儲和提供它所擁有數據的查詢(訪問器和修改器)。DTO是簡單對象,不包含任何需要測試的業務邏輯。

Entity/PO

  持久化對象PO(Persistent Object)等同於Entity,它們的概念是一致的。數據庫表中的記錄在java對象中的顯示狀態。最形象的理解就是一個PO對象對應數據庫中的一條記錄,一個PO的數據結構對應着庫中一張表的表結構,即自身屬性與數據表字段一一對應。好處是可以把一條記錄作為一個對象處理,方便的轉為其它對象。

  例如我們有一條數據,現在有一個簡單類而且已經是被賦予了這條數據的實例,那么這條數據在這個簡單類中的存在狀態就是PO,不管這個簡單類是DO還是BO抑或其它。PO只是數據持久化的一個狀態。

  通常PO里面除了get,set之外沒有別的方法。對於PO來說,數量是相對固定的,一定不會超過數據庫表的數量。

DO

  領域對象 DO(Domain Object) 是從現實世界中抽象出來的有形或無形的業務實體,它用來接收數據庫對應的實體,是一種抽象化的數據狀態,介於數據庫與業務邏輯之間。

  一般在業務邏輯層(Service)對數據庫(SQL) 進行訪問時,用於接收數據。xxxDO,xxx即為數據表名。另外,DO與Entity的不同點就是DO是與數據庫存在着某種映射關系的Entity,總的來說DO是Entity的一種。

  現在主要有兩個版本一個是阿里巴巴的開發手冊中定義的DO( Data Object),這個等同於上面的PO;另一個是在DDD(Domain-Driven Design)領域驅動設計中定義的DO(Domain Object),這個等同於上面的BO。

BO

  業務對象(Business Object,BO)是對數據進行檢索和處理的組件,主要作用是把業務邏輯封裝為一個對象,這個對象可以包括一個或多個其它的對象。形象描述為一個對象的形為和動作,當然也有涉及到其它對象的一些形為和動作。

  BO通常位於中間層或者業務邏輯層。BO支持序列化和反序列化,可以輕易地將BO的Java實例轉換為一個XML文件或者一個流保存起來,並且在需要的時候,將這個BO從XML或者流中轉換回一個Java實例。舉個簡單的例子,一個簡歷包含教育經歷、工作經歷、社會關系等三個模塊,每個模塊對應一個PO;建立一個BO對象處理簡歷,則每個BO包含這三個PO。

  應用中的所有實體(Entity)都是BO,但並不是所有BO都是實體。BO包括包含方法的實體對象(Entity Object)和不包含方法的值對象(VO)。

Model

  Model是數學邏輯名詞,包括有限操作的集合以及定義於其上的關系,主要用於分析、設計過程。

  實體類和模型Model在計算機程序設計中有兩個概念:一個是三層架構中的實體類,另一個是MVC架構中的模型。在“三層架構”中,為了面向對象編程,將各層傳遞的數據封裝成實體類,便於數據傳遞和提高可讀性。在MVC(模型Model-視圖View-控制器Controller)模式中,Model代表模型,是業務流程/狀態的處理以及業務規則的制定,接受視圖請求的數據,並返回最終的處理結果。業務模型的設計可以說是MVC最主要的核心。

View

  在MVC模式中,View代表視圖,用來解析Model帶來的數據模型,以展示視圖數據,View的模型覺決定了需要什么樣的Model來對接,相互聯系。

DAO

  數據訪問對象DAO (Data Access Object)是一個數據訪問接口,所謂數據訪問,顧名思義,就是與數據庫打交道,夾在業務邏輯與數據庫資源中間。
一般在業務邏輯層對數據庫進行訪問時使用。

  xxxDAO,xxx即為實體類名(Entity實體)。在核心J2EE模式中是這樣介紹DAO模式的:為了建立一個健壯的J2EE應用,應該將所有對數據源的訪問操作抽象封裝在一個公共API中。用程序設計的語言來說,就是建立一個接口,接口中定義了此應用程序中將會用到的所有事務方法。在這個應用程序中,當需要和數據源進行交互的時候就使用這個接口,並且編寫一個單獨的類或者xml文件,來實現這個接口在邏輯上對特定數據的操作。

放在哪個目錄

  • PO通常放在名為bean、entity、model目錄中。
  • DAO通常在DAO、mapper目錄中。
  • BO通常在service、manager、business目錄中。

POJO的擴展

  POJO僅包含最簡單的字段屬性,沒有多余的東西,它本質上就是一個普通的JavaBean。但是在POJO的基礎上,能夠擴展出不同的對象。

  • 為POJO增加了持久化的方法(Insert、Update、Delete……)之后,POJO就變成了PO。

  • 為POJO增加了數據綁定功能之后,POJO就變成了View Object,即UI Model。

  • 為POJO增加業務邏輯的方法(比如單據審核、轉帳……)之后,POJO就變成了Domain Model。

  • POJO還可以當作DTO使用。

  文章到這里就結束了,看完之后你有什么想法想要跟大家分享呢?評論區在等着你!

Reference


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM