Đối với tôi, điều này có ý nghĩa vì nó đặt một cái tên cụ thể cho lớp, thay vì dựa vào NamedEntity chung. Mặt khác, có một số lớp như vậy đơn giản là không có thuộc tính bổ sung.
Có bất kỳ nhược điểm của phương pháp này?
Cách tiếp cận không tệ, nhưng có những giải pháp tốt hơn. Nói tóm lại, một giao diện sẽ là một giải pháp tốt hơn cho việc này. Lý do chính tại sao giao diện và kế thừa khác nhau ở đây là vì bạn chỉ có thể kế thừa từ một lớp, nhưng bạn có thể thực hiện nhiều giao diện .
Ví dụ, hãy xem xét rằng bạn đã đặt tên cho các thực thể và các thực thể được kiểm toán. Bạn có một vài thực thể:
One
không phải là một thực thể được kiểm toán cũng không phải là một thực thể được đặt tên. Điều đó thật đơn giản:
public class One
{ }
Two
là một thực thể được đặt tên nhưng không phải là một thực thể được kiểm toán. Đó chính là những gì bạn có bây giờ:
public class NamedEntity
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Two : NamedEntity
{ }
Three
là cả một mục được đặt tên và kiểm toán. Đây là nơi bạn gặp phải một vấn đề. Bạn có thể tạo một AuditedEntity
lớp cơ sở, nhưng bạn không thể Three
kế thừa cả hai AuditedEntity
và NamedEntity
:
public class AuditedEntity
{
public DateTime CreatedOn { get; set; }
public DateTime UpdatedOn { get; set; }
}
public class Three : NamedEntity, AuditedEntity // <-- Compiler error!
{ }
Tuy nhiên, bạn có thể nghĩ đến một cách giải quyết bằng cách AuditedEntity
thừa kế từ NamedEntity
. Đây là một cách hack thông minh để đảm bảo rằng mọi lớp chỉ cần kế thừa (trực tiếp) từ một lớp khác.
public class AuditedEntity : NamedEntity
{
public DateTime CreatedOn { get; set; }
public DateTime UpdatedOn { get; set; }
}
public class Three : AuditedEntity
{ }
Điều này vẫn hoạt động. Nhưng những gì bạn đã làm ở đây được tuyên bố rằng mọi thực thể được kiểm toán vốn dĩ cũng là một thực thể được đặt tên . Điều này đưa tôi đến ví dụ cuối cùng của tôi. Four
là một thực thể được kiểm toán nhưng không phải là một thực thể được đặt tên. Nhưng bạn không thể để Four
thừa kế từ đó AuditedEntity
như bạn cũng sẽ biến nó thành NamedEntity
do sự kế thừa giữa AuditedEntity and
NamedEntity`.
Sử dụng tính kế thừa, không có cách nào để tạo cả hai Three
và Four
hoạt động trừ khi bạn bắt đầu sao chép các lớp (điều này mở ra một loạt các vấn đề mới).
Sử dụng giao diện, điều này có thể dễ dàng đạt được:
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; }
}
Hạn chế nhỏ duy nhất ở đây là bạn vẫn phải thực hiện giao diện. Nhưng bạn nhận được tất cả lợi ích từ việc có một loại có thể tái sử dụng chung, không có bất kỳ nhược điểm nào xuất hiện khi bạn cần các biến thể trên nhiều loại phổ biến cho một thực thể nhất định.
Nhưng tính đa hình của bạn vẫn còn nguyên:
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);
Mặt khác, có một số lớp như vậy đơn giản là không có thuộc tính bổ sung.
Đây là một biến thể trên mẫu giao diện đánh dấu , trong đó bạn thực hiện một giao diện trống hoàn toàn để có thể sử dụng loại giao diện để kiểm tra xem một lớp nhất định có được "đánh dấu" với giao diện này không.
Bạn đang sử dụng các lớp kế thừa thay vì các giao diện được triển khai, nhưng mục tiêu là như nhau, vì vậy tôi sẽ gọi nó là "lớp được đánh dấu".
Theo mệnh giá, không có gì sai với các giao diện / lớp đánh dấu. Chúng có giá trị về mặt cú pháp và kỹ thuật, và không có nhược điểm cố hữu khi sử dụng chúng với điều kiện là điểm đánh dấu là hoàn toàn đúng (tại thời gian biên dịch) và không có điều kiện .
Đây chính xác là cách bạn nên phân biệt giữa các ngoại lệ khác nhau, ngay cả khi những ngoại lệ đó không thực sự có bất kỳ thuộc tính / phương thức bổ sung nào so với phương thức cơ sở.
Vì vậy, không có gì sai khi làm như vậy, nhưng tôi sẽ khuyên bạn nên thận trọng khi sử dụng, đảm bảo rằng bạn không chỉ đang cố che đậy một lỗi kiến trúc hiện có với đa hình được thiết kế xấu.
OrderDateInfo
s với các phương pháp có liên quan đến cácNamedEntity
s khác