你是不是已經厭倦了和資料庫表一一對應的Model或Entity?
Ok~我們現在嘗試真正的用物件導向的思想去設計我們的業務實體類吧....
註:這裡我並不是說和資料庫表一一對應的Model這種做法有多麼不好,因為畢竟表驅動設計模式經過這麼多年的實踐,到現在也具有很強的生命力 。並且我也用這樣的設計做項目多年,可是一直存在一個疑惑,為啥在處理業務的時候大牛們所鼓吹的物件導向編程思想幾乎一點都沒用到呢?所以這裡我們做一下新的嘗試,也許由於各種具體實現技術的限制和我水平有限這種嘗試可能並不徹底...
- 按照國際慣例,我們建立一個抽象類別,作為我們系統中所有業務對象的基類,將來可以用來識別哪些類是我們自己的業務對象類
namespace Demo.HIS.FrameWork.DomainBase
{
/// <summary>
/// 系統所有業務類都要繼承的基類
/// </summary>
[Serializable]
public abstract class BaseObject
{
}
}
- 一般在資訊管理系統中,大多數的業務對象都需要持久到資料庫,所以我們再建立一個抽象類別作為所有可以被持久化的業務對象都要繼承的基類
代碼namespace Demo.HIS.FrameWork.DomainBase
{
/// <summary>
/// 可以持久到資料庫的業務類都要繼承的基類
/// </summary>
public abstract class Entity : BaseObject
{
public Entity()
{
Id = Guid.NewGuid().ToString();
CreateTime = DateTime.Now;
IsDelete = false;
}
public virtual string Id { get; protected set; }
public virtual DateTime CreateTime { get; protected set; }
public virtual bool IsDelete { get; set; }
public virtual Int32 Version { get; protected set; }
}
}
a.Entity繼承了BaseObject。因為Entiy也是業務對象,只不過它是可以持久化的業務對象。
b.為啥所有屬性都要用virtual? 因為我們需要用NHibernate來做持久化,它要求屬性必須是virtual,如果你還要問為啥NHibernate需要用virtual,據我所知NHibernate移植自Java的Hibernate,在Java裡virtual是常態,為了移植方便 所以沿用...其實就算NHibernate不需要virtual,我也會寫成virtual....這樣子類可以重寫,是不是很羅嗦....?
c.所有可以持久到資料庫中對象都有Id屬性,別告訴你資料庫裡的表沒有Id欄位做為主鍵(特殊情況可能沒有...比如多對多關聯表)。為啥我的Id資料類型是string? 項目很大,生命週期也長,指不定啥時候因為某種原因需要改變Id的資料類型(我就遇到過...)所以我們不把Id的資料類型定死為int或guid,而且把Id的產生方式放在這個基類的建構函式裡,注意Id = Guid.NewGuid().ToString();這裡我們的Id產生方式採用GUID。
d.為了防止誤刪除,以及一些表間關聯情況下刪除而導致程式出錯,我們系統中預設的刪除一般都是邏輯刪除,所以用IsDelete欄位進行標識(這樣可能產生不少垃圾資料,以後我們可以進行到期刪除處理或轉移之類的功能來避免)。
e.Version欄位是 提供給NHibernate處理並發用的。
f.CreateTime有啥用?我也不知道....
應用情境舉例之InputItem
在我們的項目中經常需要用到各種下拉選擇項,而且客戶要求很BT,供選擇的項可能從幾個到上萬個不等,而且為了快速錄入需要模糊輸入漢字,編碼,拼音,五筆都可以檢索到想要選擇的項,如(這是B/S的用EXT實現):
於是我們想到為系統中所有需要這樣錄入的對象建立一個基類:
代碼namespace Demo.HIS.FrameWork.DomainBase
{
/// <summary>
/// 下拉輸入項實體
/// </summary>
public abstract class InputItem : Entity
{
private string name;
private string code;
/// <summary>
/// 文本值
/// </summary>
public virtual string Name
{
get
{
return this.name;
}
set
{
if (String.IsNullOrEmpty(value))
throw new NotNullException();
this.name = value;
}
}
/// <summary>
/// 編碼
/// </summary>
public virtual string Code
{
get
{
return this.code;
}
set
{
if (String.IsNullOrEmpty(value))
throw new NotNullException();
this.code = value;
}
}
/// <summary>
/// 助記碼
/// </summary>
public virtual string InputCode1 { get; set; }
/// <summary>
/// 助記碼2
/// </summary>
public virtual string InputCode2 { get; set; }
/// <summary>
/// 助記碼3
/// </summary>
public virtual string InputCode3 { get; set; }
}
}
NotNullException是我定義的異常類 ,這裡可以暫時不用管它
有了這個類,如的那個“服務項目類”我們可以這樣寫:代碼
namespace Demo.HIS.Infrastructure.Core
{
/// <summary>
/// 服務項目
/// </summary>
public class ServiceItem : InputItem
{
//ServiceItem屬性1
//ServiceItem屬性2
}
}
應用情境舉例之User
比如在我們的項目中可能登入我們系統的使用者角色可能有 醫生,護士,患者,醫院行政人員,這幾個對象的都應該屬於系統使用者物件
所以我們可以建立一個User抽象類別,包含基本的使用者名稱,密碼等屬性,且包含一些系統使用者的方法比如登入,登出,修改密碼等等....
然後針對 醫生,護士,患者,醫院行政人員這幾個對象分別建類繼承User抽象類別,各自的對象中包含各自的屬性和方法
具體的代碼我就不貼了,反正這個系列以後會講到...
以後我們的業務對象都按照這樣的思路去設計,和以前我們單調的和資料庫表一一對應的實體類比較起來,這樣寫是不是比較OO且比較有趣一些呢?
大套的理論到處都有這裡就不吹了,至少我個人覺得這樣寫感覺上比較有設計感一些,而且對於應對需求變更的應付能力也強了很多