在.NET中使用域?qū)ο蟪掷m(xù)模式
發(fā)表時間:2024-06-15 來源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]域應用程序?qū)ο笸ǔJ钦麄應用程序的中心,被很多子系統(tǒng)使用。它們表現(xiàn)了核心的數(shù)據(jù)和業(yè)務驗證規(guī)則;因此,良好的域?qū)ο笤O計對于牢固的、高性能的和靈活的應用程序非常關(guān)鍵。 當我們開發(fā)那些使用了關(guān)系數(shù)據(jù)庫的面向?qū)ο髴贸绦虻臅r候,建立與數(shù)據(jù)庫設計一致的域?qū)ο笤O計可以使應用程序更容易理解,這是因為在典型情...
域應用程序?qū)ο笸ǔJ钦麄應用程序的中心,被很多子系統(tǒng)使用。它們表現(xiàn)了核心的數(shù)據(jù)和業(yè)務驗證規(guī)則;因此,良好的域?qū)ο笤O計對于牢固的、高性能的和靈活的應用程序非常關(guān)鍵。
當我們開發(fā)那些使用了關(guān)系數(shù)據(jù)庫的面向?qū)ο髴贸绦虻臅r候,建立與數(shù)據(jù)庫設計一致的域?qū)ο笤O計可以使應用程序更容易理解,這是因為在典型情況下,域?qū)ο蟊憩F(xiàn)了現(xiàn)實的"實體"和它們彼此之間的關(guān)系。因此,在很多情形下,域?qū)ο蠖急?quot;映射"為關(guān)系數(shù)據(jù)庫表和表間關(guān)系。但是,這種映射非常容易出錯,從而以不合需要的域?qū)ο笤O計為終結(jié)。域?qū)ο蟮牧己迷O計要求開發(fā)者對面向?qū)ο蠛完P(guān)系的基本原理有深刻的理解。
域?qū)ο蟪掷m(xù)(Domain Objects Persistence)模式試圖提供一種向關(guān)系數(shù)據(jù)庫的映射關(guān)系,解除域?qū)ο笈c持續(xù)性邏輯之間的耦合關(guān)系。在這種模式中,域?qū)ο笞陨硎遣恢莱掷m(xù)性機制的,因為其依賴關(guān)系是單方向的(從持續(xù)性對象到域?qū)ο螅。這簡化了域?qū)ο蟮脑O計,使它們更容易理解。它也向應用程序中的那些使用了域?qū)ο蟮淖酉到y(tǒng)隱藏了持續(xù)性對象。更好的是,這種模式可以在分布式系統(tǒng)中使用,在這種情況下,只有域?qū)ο笏奶巶鬟f,使應用程序不用把持續(xù)機制暴露給外部代碼。本文演示了如何使工廠(Factory)模式和域?qū)ο蟪掷m(xù)模式一起工作,來幫助域?qū)ο笈c持續(xù)性邏輯解除耦合。
定義問題
域?qū)ο笫撬袘贸绦虻闹袠。它們捕獲了數(shù)據(jù)庫的核心數(shù)據(jù)模型和應用在數(shù)據(jù)上的業(yè)務規(guī)則。在典型情況下,應用程序的大多數(shù)子系統(tǒng)都依賴這些通用的域?qū)ο?-這意味著域?qū)ο蟮挠成湓浇咏鼣?shù)據(jù)庫大綱,應用程序開發(fā)者理解和使用它們就越容易,因為它們表現(xiàn)了數(shù)據(jù)庫中的現(xiàn)實"實體"和"關(guān)系"。
如果域?qū)ο鬀]有與應用程序的其它部分分開,你通常就得把持續(xù)性代碼復制到很多個位置。同樣,如果域?qū)ο鬀]有與持續(xù)性代碼分開,你遇到的情況就是,任何使用域?qū)ο蟮淖酉到y(tǒng)都必須知道并依賴持續(xù)性對象。對持續(xù)性對象的任何更改都必然影響整個應用程序。因此,如果沒有把域?qū)ο笈c應用程序和持續(xù)性代碼分開都是不好的設計。
定義解決方案
實現(xiàn)上述目標的一個途徑是把域?qū)ο蠓蛛x到一個獨立的子系統(tǒng)中,讓應用程序的其它部分需要域數(shù)據(jù)的時候再使用它們。此外,你還必須把域?qū)ο笈c持續(xù)性代碼分開。一方面,這種雙重分離避免了代碼重復;另一方面,它向域?qū)ο箅[藏了持續(xù)性細節(jié)信息,建立了更容易修改的靈活設計。無論數(shù)據(jù)來自關(guān)系數(shù)據(jù)庫、XML文件、平面文件、活動目錄/LDAP或其它任何數(shù)據(jù)源,域?qū)ο蠛蛻贸绦虻钠渌糠侄纪耆粫艿接绊憽?br>
在分離持續(xù)性邏輯和域?qū)ο蟮倪^程中,你必須確保域?qū)ο鬀]有依賴持續(xù)性代碼。這樣操作允許你把域?qū)ο蟊┞对谀切┠悴幌M┞冻掷m(xù)性代碼的地方。
建立示例
下面的C#示例使用了Northwind示例數(shù)據(jù)庫的Customer對象,它映射到數(shù)據(jù)庫的Customer表。
public class Customer {
// 私有數(shù)據(jù)成員
String _customerId;
String _companyName;
String _contactName;
String _contactTitle;
public Customer() {}
// Customer對象的屬性
public String CustomerId {
get { return _customerId; }
set { _customerId = value;}
}
public String CompanyName {
get { return _companyName; }
set { _companyName = value;}
}
public String ContactName {
get { return _contactName; }
set { _contactName = value;}
}
public String ContactTitle {
get { return _contactTitle; }
set { _contactTitle = value;}
}
}
public interface ICustomerFactory {
// 用于單行操作的標準事務方法
void Load(Customer cust);
void Insert(Customer cust);
void Update(Customer cust);
void Delete(Customer cust);
// 返回集合的查詢方法
ArrayList FindCustomersByState(String state);
}
public class CustomerFactory : ICustomerFactory
{
//用于單行操作的標準事務方法
void Load(Customer cust) { /* Implement here */ }
void Insert(Customer cust) { /* Implement here */ }
void Update(Customer cust) { /* Implement here */ }
void Delete(Customer cust) { /* Implement here */ }
//返回集合的查詢方法
ArrayList FindCustomersByState(String state) {
/* 此處是實現(xiàn)代碼 */
}
}
下面的示例演示了客戶端如何使用這段代碼。
public class NorthwindApp
{
static void Main (string[] args) {
Customer cust = new Customer();
CustomerFactory custFactory = new CustomerFactory();
//從Northwind數(shù)據(jù)庫載入客戶
cust.CustomerId = "ALFKI";
custFactory.load(cust);
// 傳遞 Customer 對象
FooBar(cust);
// custList是Customer對象列表
ArrayList custList = custFactory.FindCustomersByState("CA");
}
}
在上面代碼中,load方法根據(jù)CustomerID(應用程序可以把這個值傳遞到任何子系統(tǒng)中而不需要暴露持續(xù)性代碼)從數(shù)據(jù)庫中載入Customer對象。同樣,如果你載入Customer對象的數(shù)組列表,你隨后也可以傳遞數(shù)組列表,也沒有持續(xù)性代碼依賴。
使用域?qū)ο蟪掷m(xù)模式分離持續(xù)性代碼和Customer對象,使得Customer對象更加面向?qū)ο,更易于理解,因為它的對象模型更加接近于?shù)據(jù)庫中的數(shù)據(jù)模型。此外,這種分離使你能夠把Customer傳遞到應用程序的不同部分(甚至于通過.NET Remoting傳遞到分布式應用程序),而不需要暴露持續(xù)性代碼。