2012-09-25 36 views
5

Tôi vừa học được một chút về Thành phần trên thừa kế. Tôi đã tự hỏi nếu tôi nên áp dụng các khái niệm cho một cái gì đó tôi đã viết gần đây.Lớp cơ sở hoặc trợ giúp trừu tượng

Chúng tôi trước đây có hai lớp là gần như giống hệt nhau, ngoài một vài khác biệt nhỏ. Chúng chứa một số tính năng truy cập cơ sở dữ liệu cơ bản, nhưng hoạt động trên các kiểu đối tượng khác nhau (nhưng có liên quan). Vì vậy, trước đây chúng tôi đã có lớp được cấu trúc một cái gì đó như thế này:

class BallMillDBHandler{ 

    public BallMillDBHandler(){ ... } 

    public void InsertTool(BallMill tool) { ... } 
    public BallMill QueryTool(string toolID) { ... } 
    public void UpdateTool(BallMill tool) { ... } 
    public void DeleteTool(string toolID) { ... } 
} 

class DiamondToolDBHandler{ 

    public DiamondToolDBHandler(){ ... } 

    public void InsertTool(DiamondTool tool) { ... } 
    public DiamondTool QueryTool(string toolID) { ... } 
    public void UpdateTool(DiamondTool tool) { ... } 
    public void DeleteTool(string toolID) { ... } 
} 

tôi mất phần lớn các phương pháp gần trùng lặp và refactored chúng ra thành một lớp BaseToolDBHandler(), và thừa hưởng nó từ hai người kia, cung cấp một vài phương pháp trừu tượng và các thuộc tính để xử lý các khác biệt trong việc truy cập các tham số cơ sở dữ liệu.

Có ý nghĩa khi đặt lớp trợ giúp BaseToolDBHandler thay thế, được chứa bên trong trình truy cập cơ sở dữ liệu và cung cấp cho họ giao diện chung các thuộc tính/phương thức trừu tượng trước đây không? Hay tôi nên để nó như một trường hợp thừa kế?

+5

Nghe có vẻ như là nơi hoàn hảo để thừa hưởng tôi nên tôi sẽ để nó theo cách đó. –

+0

Neil Kennendy đúng. Nhưng nếu BaseClass của bạn chỉ cung cấp các phương thức trừu tượng và các thuộc tính và không bao giờ cung cấp bất kỳ chức năng được triển khai nào sử dụng một giao diện thay thế (e.G. 'IDBHandler '). –

Trả lời

3

Điều này giống như một kịch bản có thể mang lại lợi ích cho cả generics và thừa kế thông qua một lớp cơ sở/giao diện.

class DBHandler<TTool> where TTool : ToolBase // or ITool 
{ 
    public DBHandler(){ ... } 

    public void InsertTool(TTool tool) { ... } 
    public TTool QueryTool(string toolID) { ... } 
    public void UpdateTool(TTool tool) { ... } 
    public void DeleteTool(string toolID) { ... } 
} 

Nếu bạn cần, bạn có thể tạo ra một cơ sở (tùy chọn trừu tượng) lớp, hoặc một giao diện để sử dụng như một loại hạn chế đó sẽ đảm bảo chắc chắn các thành viên mà bạn cần những công cụ để có bên trong cơ thể phương pháp.

Ví dụ:

var handler = new DBHandler<BallMill>(); 
BallMill value = handler.QueryTool("xyz"); 
value.SomeProperty = "New Value"; 
handler.UpdateTool(value); 
+1

Điều này có vẻ như nó có thể là một lựa chọn, nhưng nó sẽ phụ thuộc vào những gì xảy ra bên trong những phương pháp đó; họ có thể hoặc có thể không đủ tương tự để làm việc này. – Servy

+0

@Jamiec Thật vậy. Hiểu rồi. – Dan

+0

Tôi nghĩ việc tạo cơ sở chung sẽ giúp ích rất nhiều. Tôi vẫn cần phải duy trì một tập hợp các tham số khác nhau mà theo đó DB được truy cập, và tôi nghĩ việc giữ các tham số đó trong các lớp riêng biệt tốt hơn là chuyển chúng vào trong mỗi trường hợp. Nhưng điều này là hữu ích, tôi nghĩ tôi sẽ đánh dấu nó là câu trả lời được chấp nhận. – KChaloux

3

Thừa kế không có xu hướng được sử dụng quá mức, nhưng điều này có vẻ giống như một trường hợp thích hợp cho nó. Trong nhiều trường hợp, mọi người chỉ thấy mã trùng lặp và nghĩ rằng "Tôi sẽ sử dụng thừa kế để xóa mã trùng lặp thông qua lớp cơ sở". Trong thực tế, hầu hết mã trùng lặp có thể được cấu trúc lại thành một lớp khác hoàn toàn được sử dụng ở một số nơi. Thông thường các lớp học sử dụng nó không phải là "liên quan" họ đang làm hai điều hoàn toàn khác nhau và chỉ xảy ra để chia sẻ sự cần thiết phải làm một số (hoặc một số loạt) nhiệm vụ nhỏ.

Thừa kế nên được sử dụng khi các lớp khi bạn thực sự có thể nói rằng lớp lớp "là" một thể hiện của lớp cơ sở, không chỉ một số lớp cần truy cập vào một loạt các phương thức được định nghĩa ở nơi khác. Trong trường hợp cụ thể của bạn, rõ ràng là cả hai lớp học trình xử lý DB. Tại điểm mấu chốt của họ, cả hai đều đang phục vụ cùng một mục tiêu chung, nhưng họ là hai cách triển khai khác nhau có thể có của mục tiêu đó. Vấn đề duy nhất mà tôi có thể thấy ở đây (cho rằng bạn không hiển thị nội dung của bất kỳ phương thức nào) là bạn có thể kết hợp cả hai lớp vào một lớp, nhưng chúng ta cần biết thêm chi tiết về biết nếu đó là có thể hoặc thích hợp hơn.

+0

Tôi thích định nghĩa của bạn về thời điểm sử dụng thừa kế - nó không chỉ là "có một" có "định nghĩa", nhưng bạn thực sự giải thích rằng các lớp này có cùng mục tiêu chung (và do đó có thể cần phải tham khảo chúng) theo cách đa hình nên có lý do chính đáng để sử dụng thừa kế). Khác với điều đó không có lợi ích thực sự từ thừa kế vì tái sử dụng mã có thể đạt được bằng thành phần mà không có sự ghép nối và nguy hiểm có thể xảy ra với thừa kế. – BornToCode

0

tôi sẽ nói điều này chắc chắn là một nhiệm vụ cho các thừa kế ... nhưng cho phép được một điều thẳng đầu tiên. Thành phần là mẫu thiết kế có thể và nên được sử dụng khi nhiều thừa kế của các lớp không phải là một tính năng của ngôn ngữ đã cho (ví dụ: C# chẳng hạn)

Thành phần ngụ ý rằng lớp của bạn sẽ được kế thừa. Trong trường hợp này, bạn cung cấp hợp đồng để thực hiện thông qua giao diện.

Để cung cấp cho bạn một ví dụ thô về cách thừa kế có thể được áp dụng cho mã của bạn, hãy xem xét điều này: (đây không phải là sử dụng thành phần)

public interface IHandler 
{ 
    void InsertTool(ITool tool); 
    void UpdateTool(ITool tool); 
    void DeleteTool(string toolID); 
    //void DeleteTool(ITool tool) - seems more consistent if possible!? 

    ITool QueryTool(string toolID); 
} 

public interface ITool 
{ 

} 

class BallMill : ITool 
{ 
} 

class DiamondTool : ITool 
{ 
} 

class BallMillDBHandler : IHandler 
{ 

    public BallMillDBHandler(){ ... } 

    public void InsertTool(ITool tool) { ... } 
    public BallMill QueryTool(string toolID) { ... } 
    public void UpdateTool(ITool tool) { ... } 
    public void DeleteTool(string toolID) { ... } 
} 

class DiamondToolDBHandler : IHandler 
{ 

    public DiamondToolDBHandler(){ ... } 

    public void InsertTool(ITool tool) { ... } 
    public DiamondTool QueryTool(string toolID) { ... } 
    public void UpdateTool(ITool tool) { ... } 
    public void DeleteTool(string toolID) { ... } 
} 
+0

'QueryTool' không nằm trên giao diện khá nhiều cơ sở câu trả lời này là IMO không hoạt động được. Giao diện không thực sự sử dụng. – Jamiec

+0

@Jamiec ... thời gian để chỉnh sửa ... – series0ne

0

Thay vì thừa kế, sử dụng Generics. Bạn muốn thực hiện cùng một thao tác trên các loại đối tượng khác nhau, đó chính xác là những gì generics làm tốt nhất.

Các vấn đề liên quan