Абстрактный класс или интерфейс для сервиса IoC?
В настоящее время я использую IoC для предоставления конкретных реализаций репозиториев в проекте. Все примеры, которые я прочитал, используют интерфейс в качестве определения сервиса. Однако, прочитав рекомендации от Microsoft, рекомендуется отдавать предпочтение абстрактным классам над интерфейсами.
Я нашел это полезным в сочетании с шаблоном шаблона, чтобы уменьшить количество повторений. Например дать Product
класс со свойством IsActive
Я мог бы использовать интерфейс для хранилища, такой как:
interface IProductRepository
{
IEnumerable<Product> Load();
}
Если общей задачей является загрузка активных продуктов, то мне нужно сделать:
IEnumerable<Product> activeProducts = repository.Load().Where(x => x.IsActive);
куда repository
это конкретная реализация. Если бы я использовал абстрактный класс, такой как:
abstract class ProductRepository
{
protected abstract IEnumerable<Product> LoadCore();
public IEnumerable<Product> Load()
{
return LoadCore().Where(x => x.IsActive);
}
}
Тогда я мог бы загружать активные продукты, используя
IEnumerable<Product> activeProducts = repository.Load();
Вся реализация для загрузки информации о продукте находится в конкретном классе, который выводит ProductRepository
поэтому нет связи с постоянным слоем. Если будет обнаружено, что существует другое обычно выполняемое действие, то оно может быть добавлено к базовому классу как неразрывное изменение, которое не может быть выполнено с использованием интерфейса.
Есть ли польза от использования интерфейса вместо абстрактного класса? С какими потенциальными недостатками использования абстрактных классов я могу столкнуться?
Я использую Castle Windsor в качестве контроллера IoC и.Net Framework 3.5.
2 ответа
Я не думаю, что этот вопрос зависит от IoC; большинству этих фреймворков все равно, какие вы используете.
Большая проблема между использованием интерфейсов над абстрактными базовыми классами заключается в том, что интерфейсы не могут быть хорошо версионированы.
Абстрактные базовые классы обычно являются лучшим выбором из-за этого. Я не думаю, что есть какой-то недостаток в использовании абстрактного базового класса, кроме вопросов о поддержке типа "почему я не могу создать экземпляр этого типа?"
Рекомендация исходит из Руководства по разработке структуры. Эта рекомендация Microsoft существует специально для многократно используемых библиотек классов. Другими словами: фреймворки, подобные самой платформе.NET. Если вы создаете бизнес-приложение, это руководство не применяется. Это не применимо, потому что маловероятно, что у вас будут проблемы с версиями в бизнес-приложениях, потому что у вас есть контроль над всем клиентским кодом, который взаимодействует с вашими классами / интерфейсами. Это, конечно, не относится к повторно используемым библиотекам.
Даже статья Фила Хаака, где Уилл ссылается на это, описывает это:
Опять же, эти рекомендации относятся к разработке Framework (для статически типизированных языков), а не к другим типам разработки программного обеспечения.
Поэтому удаление проблем управления версиями, вероятно, не является хорошим аргументом для использования базовых классов. Сохранение кода СУХОЙ, однако, может быть. Однако использование базовых классов и интерфейсов не является взаимоисключающим; ты можешь позволить своему abstract class ProductRepository
воплощать в жизнь IProductRepository
, Однако, если вы сделаете это, разоблачение чего-либо еще, кроме IProductRepository
было бы плохой идеей.