LSP - практический подход
Везде, где я ищу примеры LSP на C #, люди использовали воображаемые классы и интерфейсы.Вот практическая реализация LSP, которую я реализовал в одной из наших систем.
Сценарий. Предположим, у нас есть 3 базы данных (клиенты по ипотечным кредитам, клиенты по текущим счетам и клиенты по сберегательному счету), которые предоставляют данные клиентов, и нам нужны данные клиентовдля данной фамилии клиента.Теперь мы можем получить более 1 информации о клиентах из этих 3 баз данных по данной фамилии.
Реализация:
БИЗНЕС МОДЕЛЬНЫЙ СЛОЙ:
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 retrieve the customer details
}
}
Этот абстрактный класс имеет общий метод "GetDetails" для всех 3базы данных, которые расширяются каждым классом базы данных, как показано ниже
ДОСТУП К ДАННЫМ ЗАКАЗЧИКА ЗАКАЗЧИКА:
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 класса доступа к данным установлены, теперь мы обращаем наше внимание на клиента.На бизнес-уровне у нас есть класс CustomerServiceManager, который возвращает сведения о клиенте своим клиентам.
БИЗНЕС-СЛОЙ:
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 и предоставляет его объект базы данных.
Конечно, нам нужны идентичные хранимые процедуры во всех участвующих базах данных.
Наконец, клиент для CustomerServiceManager
класса будет вызывать только метод GetCustomerDetails, передавать lastName и не должен заботиться о том, как и откуда поступают данные.
Надеюсь, это даст вам практическийподход к пониманию LSP.