1. 程式人生 > 其它 >淺析領域驅動模型VO、DTO、BO、PO 等的概念及其區別

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

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

摘要:淺析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


  讀後有收穫,小禮物走一走,請作者喝咖啡。

讚賞支援