利斯科夫替代原則
為什麼要使用 LSP
場景: 假設我們有 3 個資料庫(抵押客戶,經常賬戶客戶和儲蓄賬戶客戶)提供客戶資料,我們需要客戶的姓氏客戶詳細資訊。現在,根據給定的姓氏,我們可以從這 3 個資料庫中獲得超過 1 個客戶詳細資訊。
履行
商業模式層:
public class Customer
{
// customer detail properties...
}
資料訪問層:
public interface IDataAccess
{
Customer GetDetails(string lastName);
}
上面的介面由抽象類實現
public abstract class BaseDataAccess : IDataAccess
{
/// <summary> Enterprise library data block Database object. </summary>
public Database Database;
public Customer GetDetails(string lastName)
{
// use the database object to call the stored procedure to retirve the customer detials
}
}
這個抽象類為所有 3 個資料庫都有一個通用方法 GetDetails
,它由每個資料庫類擴充套件,如下所示
抵押客戶資料訪問:
public class MortgageCustomerDataAccess : BaseDataAccess
{
public MortgageCustomerDataAccess(IDatabaseFactory factory)
{
this.Database = factory.GetMortgageCustomerDatabase();
}
}
當前賬戶客戶資料訪問:
public class CurrentAccountCustomerDataAccess : BaseDataAccess
{
public CurrentAccountCustomerDataAccess(IDatabaseFactory factory)
{
this.Database = factory.GetCurrentAccountCustomerDatabase();
}
}
節省賬戶客戶資料訪問:
public class SavingsAccountCustomerDataAccess : BaseDataAccess
{
public SavingsAccountCustomerDataAccess(IDatabaseFactory factory)
{
this.Database = factory.GetSavingsAccountCustomerDatabase();
}
}
一旦設定了這 3 個資料訪問類,現在我們將注意力吸引到客戶端。在 Business 層中,我們有 CustomerServiceManager 類,它將客戶 detials 返回給客戶端。
業務層:
public class CustomerServiceManager : ICustomerServiceManager, BaseServiceManager
{
public IEnumerable<Customer> GetCustomerDetails(string lastName)
{
IEnumerable<IDataAccess> dataAccess = new List<IDataAccess>()
{
new MortgageCustomerDataAccess(new DatabaseFactory()),
new CurrentAccountCustomerDataAccess(new DatabaseFactory()),
new SavingsAccountCustomerDataAccess(new DatabaseFactory())
};
IList<Customer> customers = new List<Customer>();
foreach (IDataAccess nextDataAccess in dataAccess)
{
Customer customerDetail = nextDataAccess.GetDetails(lastName);
customers.Add(customerDetail);
}
return customers;
}
}
我沒有展示依賴注入以保持簡單,因為它現在已經變得複雜了。
現在,如果我們有一個新的客戶詳細資料庫,我們可以新增一個擴充套件 BaseDataAccess 並提供其資料庫物件的新類。
當然,我們在所有參與的資料庫中需要相同的儲存過程
最後,CustomerServiceManagerclass 的客戶端將只呼叫 GetCustomerDetails 方法,傳遞 lastName,而不應關心資料的來源和位置。
希望這能為你提供一種理解 LSP 的實用方法。