나에게 이것은 일반적인 NamedEntity에 의존하는 대신 클래스에 구체적인 이름을 부여하기 때문에 의미가 있습니다. 반면에 단순히 추가 속성이없는 많은 클래스가 있습니다.
이 방법에 단점이 있습니까?
접근 방식은 나쁘지 않지만 더 나은 솔루션이 있습니다. 요컨대, 인터페이스가 훨씬 더 나은 솔루션이 될 것입니다. 인터페이스와 상속이 다른 주된 이유 는 하나의 클래스에서만 상속 할 수 있지만 많은 인터페이스를 구현할 수 있기 때문 입니다.
예를 들어 명명 된 엔터티와 감사 된 엔터티가 있다고 가정합니다. 여러 엔티티가 있습니다.
One
감사 대상이 아니거나 지명 된 실체가 아닙니다. 간단합니다 :
public class One
{ }
Two
명명 된 엔터티이지만 감사 된 엔터티는 아닙니다. 그것은 본질적으로 당신이 지금 가지고있는 것입니다 :
public class NamedEntity
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Two : NamedEntity
{ }
Three
명명 된 및 감사 된 항목입니다. 여기서 문제가 발생합니다. 당신은 만들 수 있습니다 AuditedEntity
기본 클래스를,하지만 당신은 할 수 없습니다 Three
상속 둘 AuditedEntity
과 NamedEntity
:
public class AuditedEntity
{
public DateTime CreatedOn { get; set; }
public DateTime UpdatedOn { get; set; }
}
public class Three : NamedEntity, AuditedEntity // <-- Compiler error!
{ }
그러나에서 AuditedEntity
상속 하여 해결 방법을 생각할 수도 있습니다 NamedEntity
. 이것은 모든 클래스가 다른 클래스에서 (직접적으로) 상속받을 필요가 없도록하는 영리한 해킹입니다.
public class AuditedEntity : NamedEntity
{
public DateTime CreatedOn { get; set; }
public DateTime UpdatedOn { get; set; }
}
public class Three : AuditedEntity
{ }
이것은 여전히 작동합니다. 그러나 여기서 당신이 한 일은 모든 감사 대상이 본질적으로 명명 된 실체라고 명시되어 있습니다. 마지막 예제로갑니다. Four
감사 된 엔터티이지만 명명 된 엔터티는 아닙니다. 하지만 당신은 할 수 없습니다 Four
에서 상속 AuditedEntity
은 다음 또한이 만드는 것처럼 NamedEntity
AuditedEntity 사이의 상속에 의한 and
NamedEntity`.
상속을 사용하면 클래스 복제를 시작하지 않으면 완전히 새로운 문제가 발생하지 않는 한 둘 다 Three
만들고 Four
작동 시킬 수있는 방법이 없습니다 .
인터페이스를 사용하면 쉽게 달성 할 수 있습니다.
public interface INamedEntity
{
int Id { get; set; }
string Name { get; set; }
}
public interface IAuditedEntity
{
DateTime CreatedOn { get; set; }
DateTime UpdatedOn { get; set; }
}
public class One
{ }
public class Two : INamedEntity
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Three : INamedEntity, IAuditedEntity
{
public int Id { get; set; }
public string Name { get; set; }
DateTime CreatedOn { get; set; }
DateTime UpdatedOn { get; set; }
}
public class Four : IAuditedEntity
{
DateTime CreatedOn { get; set; }
DateTime UpdatedOn { get; set; }
}
여기서 유일한 단점은 여전히 인터페이스를 구현해야한다는 것입니다. 그러나 특정 엔티티에 대해 여러 공통 유형에 대한 변형이 필요할 때 발생하는 단점없이 공통 재사용 가능 유형을 사용하면 모든 이점을 얻을 수 있습니다.
그러나 당신의 다형성은 그대로 남아 있습니다 :
var one = new One();
var two = new Two();
var three = new Three();
var four = new Four();
public void HandleNamedEntity(INamedEntity namedEntity) {}
public void HandleAuditedEntity(IAuditedEntity auditedEntity) {}
HandleNamedEntity(one); //Error - not a named entity
HandleNamedEntity(two);
HandleNamedEntity(three);
HandleNamedEntity(four); //Error - not a named entity
HandleAuditedEntity(one); //Error - not an audited entity
HandleAuditedEntity(two); //Error - not an audited entity
HandleAuditedEntity(three);
HandleAuditedEntity(four);
반면에 단순히 추가 속성이없는 많은 클래스가 있습니다.
이것은 마커 인터페이스 패턴 의 변형으로, 인터페이스 유형을 사용하여 주어진 클래스가이 인터페이스로 "마킹"되었는지 확인할 수 있도록 빈 인터페이스를 구현합니다.
구현 된 인터페이스 대신 상속 된 클래스를 사용하고 있지만 목표는 동일하므로이를 "표시된 클래스"라고합니다.
액면가에서 마커 인터페이스 / 클래스에는 아무런 문제가 없습니다. 그것들은 구문 적으로 기술적으로 유효하며, 마커가 보편적으로 진실하고 (컴파일 타임에) 조건부가 아니라면 그것들을 사용하는 데 따른 단점이 없습니다 .
이는 예외에 실제로 기본 방법에 비해 추가 속성 / 방법이없는 경우에도 서로 다른 예외를 구별하는 방법입니다.
따라서 본질적으로 잘못된 것은 없지만, 신중하게 사용하는 것이 좋습니다. 잘못 디자인 된 다형성으로 기존의 건축 실수를 막으려는 것이 아닙니다.
OrderDateInfo
서로 관련이있는 것들의NamedEntity
의