個人BO
1-個人BO之強類型
2-個人BO之數據保護
3-個人BO之狀態控制
4-個人BO之導航屬性html
軟件的運行離不開數據,數據通常存在對象中。這種對象在 Java 統稱爲 POJO,在 C# 則爲 POCO。若 POJO 的Property(屬性)
都是可讀寫的(public
的 get
/set
),沒有方法或只有少許的持久化方法,這種稱爲貧血模型。java
貧血模型只存儲數據而對數據沒有控制,對象內部和外部都能修改。業務邏輯通常寫在外部,就算寫在內部也由於 Property 可由外界隨意修改而控制不住數據。從而這個 POJO 只是存儲數據,沒有控制數據的能力,也就沒有保護數據的能力。一個對象相關的邏輯不能被很好地集中管理,而是分散在各個外部方法中。從而產生了幾個不良後果:post
-1
,另外一處卻沒有考慮值是-1
的狀況。BO 中所有的 Property 對外都是隻讀的,外部沒法直接修改 Property。只有 BO 本身內部才能修改屬性,從而保護了數據。外部經過調用 BO 的業務方法修改一個或多個屬性,業務方法可對參數和狀態進行各類判斷,知足條件才修改數據。從而保證任什麼時候候 BO 的數據都是合法的。因爲數據只能在內部修改,因此什麼值表明什麼意思是由 BO 本身決定的,統一決定,而不是由外部分散在各個地方的代碼邏輯決定的,因此有效地保證了數據含義的統一性。this
雖然關於這個 BO 本身的業務都寫到 BO 這個類中了(這裏暫無須考慮經過繼承寫到多個類的狀況),起到了集中控制的效果。但內部不一樣的業務方法也可能有共用的邏輯,這些應該經過重構功能,以達到「一個功能只寫一處」的狀態。一個大功能會包含若干個小功能,這裏的「功能」,是泛指大大小小的任何一個功能。不管是面向對象仍是面向過程,都應該努力作到「一個功能只寫一處」。這是解決軟件靈活性與軟件正確性的惟一比較可取的作法。除非把人看成機器,面對以前大量「複製粘貼再改改」的代碼須要修改時也能絕不遺漏地所有修改。lua
BO 被定義爲任什麼時候刻都是有意義的,因此並不能new
一個空對象,而後再賦值,數據必須在new
時就送來,因此 BO 須要提供一個所有屬性的構造方法。另外爲了持久化方便的考慮,也能夠接收一個 PO,從 PO 獲取各個屬性的值。code
網上購物的訂單
示例htm
public class OrderBo extends BoBase { Order order; @Autowired OrderDB orderDB; public OrderBo(Order order) { /* 傳入 PO */ if (order == null) throw ParameterException.missData("order"); this.order = order; } public OrderBo(Long buyerId, Long postDistrictId, String postAddress, String postContactPhone, String evaluation, Date createTime, OrderStatus status, EvaluateStatus evaluateStatus) { /* 傳入各個 Property */ Order entity = new Order(); entity.setBuyerId(buyerId); entity.setPostDistrictId(postDistrictId); entity.setPostAddress(postAddress); entity.setPostContactPhone(postContactPhone); entity.setEvaluation(evaluation); entity.setCreateTime(createTime); entity.setStatus(status.toString()); entity.setEvaluateStatus(evaluateStatus); this.order = entity; this.trackState = BoTrackState.Added; } // region 屬性 public Long getId() { return order.getId(); } protected void setId(Long id) { /* 每一個 set 都不是 public */ order.setId(id); setTrackUpdate(); /* 父類方法,後續文章會介紹 */ } // 買家 Id public Long getBuyerId() { return order.getBuyerId(); } protected void setBuyerId(Long buyerId) { order.setBuyerId(buyerId); setTrackUpdate(); } // 區縣 Id public Long getPostDistrictId() { return order.getPostDistrictId(); } protected void setPostDistrictId(Long postDistrictId) { order.setPostDistrictId(postDistrictId); setTrackUpdate(); } // 詳細地址 public String getPostAddress() { return order.getPostAddress(); } protected void setPostAddress(String postAddress) { order.setPostAddress(postAddress); setTrackUpdate(); } // 聯繫手機 public String getPostContactPhone() { return order.getPostContactPhone(); } protected void setPostContactPhone(String postContactPhone) { order.setPostContactPhone(postContactPhone); setTrackUpdate(); } // 評價內容 public String getEvaluation() { return order.getEvaluation(); } protected void setEvaluation(String evaluation) { order.setEvaluation(evaluation); setTrackUpdate(); } // 下單時間,建立時間 public Date getCreateTime() { return order.getCreateTime(); } protected void setCreateTime(Date createTime) { order.setCreateTime(createTime); setTrackUpdate(); } // 訂單狀態 public OrderStatus getStatus() { String sStatus = order.getStatus(); return OrderStatus.valueOf(sStatus); } protected void setStatus(OrderStatus status) { String sStatus = status.toString(); order.setStatus(sStatus); setTrackUpdate(); } // 評價狀態:未評價,已評價 public EvaluateStatus getEvaluateStatus() { String sStatus = order.getEvaluateStatus(); return EvaluateStatus.valueOf(sStatus); } protected void setEvaluateStatus(EvaluateStatus evaluateStatus) { String sStatus = evaluateStatus.toString(); order.setEvaluateStatus(sStatus); setTrackUpdate(); } // endregion 屬性 // region 操做 public void delete() { this.setTrackDeleted(); this.save(); } // 評價 public void evaluat(string evaluation) { /* 不是特定的狀態不能評價。如有須要,能夠阻止內容爲(空)的評價 */ if (this.getEvaluateStatus() != EvaluateStatus.未評價) { throw ParameterException.invalidStatus("訂單" + this.getEvaluateStatus() + ",不能評價"); } /* 修改評價內容,並修改評價狀態,而不是內容和狀態能夠被外部分別調用! */ this.setEvaluation(evaluation); this.setEvaluateStatus(EvaluateStatus.已評價); this.save(); /* 父類方法,後續文章會介紹 */ } // endregion 操做 }
打/* */
的內容是本文特地加的說明。對象
沒有對構造時的數據進行合法性驗證。解決辦法能夠在構造時檢查,若非法則拋異常。也能夠私有化構造方法,並提供public static
方法,若非法則返回null
。blog
感謝 Rayman(QQ:25625607) 在我爲【BO 的屬性該全只讀,經過方法來修改】仍是【能夠部分屬性可寫(public set
),並在寫時做業務邏輯】猶豫不定時給我了確定的回答。我認爲這是整個 BO 的關鍵所在。繼承