개인적으로 공공 계약에서 소음을 없애고 싶을 때 개인적으로 보호 된 수정자를 사용합니다. b) 반대로도 파생 된 클래스와 기능을 공유합니다. c) DRY 코드를 작성하고 단일 책임을 염두에 두어야합니다. 원리. 전형적인 것 같지만 확실한 예를 보여 드리겠습니다.
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();
}
}
이제 다음은
는 콘크리트 위젯 쿼리 처리기은 다음과 같은 형태가 될 것이다 CachingQueryProvider 클래스에 추가 된 캐싱에 특정한 것을 사용하지 않을 것입니다. 나는 필요에 따라 캐싱을 추가/제거하거나 최소한의 노력으로도 캐싱 구현을 완전히 변경할 수 있습니다.
IQueryHandler<WidgetCommand, Widget> widgetQueryHandler;
var widgets = widgetQueryHandler.Execute(myWidgetCommand);
은 그냥 자바 독에서 몇 가지 클래스를 통해 훑어 당신은 내가 공개 방법은에서 사람에게 전혀 해를 끼치 지 이루어지지했을 사례 만보고 "실제 사용 사례"의 무리 : – zneak
를 볼 수 있습니다 (패키지 클래스가 처음부터 패키지 외부로 서브 클래스 화되도록 설계되지 않았기 때문에) 패키지 메소드가 보호 된 메소드보다 더 이해하기 쉬운 곳에서 사용할 수 있습니다. – Mecki