Я лично использую защищенный модификатор, когда хочу: а) устранить шум в публичном контракте, но б) также совместно использовать функциональные возможности с производными классами, в то время как в свою очередь в) писать код, который является СУХОЙ, а также помнить о единой ответственности принцип. Звучит типично, я уверен, но позвольте мне привести пример.
Здесь мы имеем базовый интерфейс обработчика запросов:
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);
Просто пролистать несколько классов из Javadoc, и вы увидите кучу «реальных случаев использования» :) – zneak
я вижу только те случаи, когда публичный метод не сделал бы никакого вреда никому в мир или где пакетный метод имел бы больше смысла, чем защищенный (поскольку класс не был спроектирован подклассом за пределами пакета в первую очередь). – Mecki