Я лично использую защищенный модификатор, когда хочу: а) устранить шум в публичном контракте, все же б) также делиться функциональностью с производными классами, в то же время в) в) писать код, который является СУХИМЫМ, и при этом учитывает принцип единой ответственности,Звучит типично, я уверен, но позвольте мне привести пример.
Здесь у нас есть базовый интерфейс обработчика запросов:
public interface IQueryHandler<TCommand, TEntity>
{
IEnumerable<TEntity> Execute(TCommand command);
}
Этот интерфейс реализован многими различными обработчиками запросов в приложении.Позже скажем позже, что мне нужно кешировать результаты запросов от множества различных обработчиков запросов.Это действительно просто деталь реализации, хотя.Потребители любого конкретного класса обработчика запросов, вообще говоря, не обеспокоены этим.Тогда мое решение состоит в том, чтобы создать реализацию, которая заботится о кэшировании, но переносит фактическую ответственность за запросы на любые производные классы.
public abstract class CachedQueryHandler<TCommand, TEntity>
: IQueryHandler<TCommand, TEntity>
{
public IEnumerable<TEntity> Execute(TCommand command)
{
IEnumerable<TEntity> resultSet = this.CacheManager
.GetCachedResults<TEntity>(command);
if (resultSet != null)
return resultSet;
resultSet = this.ExecuteCore(command);
this.CacheManager.SaveResultSet(command, resultSet);
return resultSet;
}
protected abstract IEnumerable<TEntity> ExecuteCore(TCommand command);
}
CachedQueryHandler не намерен ни для кого другого напрямую вызывать метод ExecuteCore.Также не важно, как реализованы запросы.Защищенный модификатор идеально подходит для такого сценария.
Кроме того, я не хочу повторять один и тот же тип кода в каждом обработчике запросов, особенно потому, что рефакторинг, если кеш будет кошмаромИзменен интерфейс менеджера, и было бы очень трудно избавиться, если бы кэширование было полностью удалено на этом уровне.
Вот как будет выглядеть конкретный обработчик запросов виджетов:
public class DatabaseWidgetQueryHandler : CachedQueryHandler<WidgetCommand, Widget>
{
protected override IEnumerable<Widget> ExecuteCore(WidgetCommand command)
{
return this.GetWidgetsFromDatabase();
}
}
Теперь, если потребители обработчика запросов виджетов используют его через интерфейс обработчика запросов, что, если я использую зависимостьВнедрение, которое я, конечно, могу применить, они никогда не будут использовать ничего особенного для кэширования, добавляемого в класс CachedQueryProvider.Затем я могу свободно добавлять / удалять кэширование по мере необходимости или полностью изменять реализацию кэширования даже при минимальных усилиях.
IQueryHandler<WidgetCommand, Widget> widgetQueryHandler;
var widgets = widgetQueryHandler.Execute(myWidgetCommand);