Giảm nồi hơi trong lớp thực hiện giao diện thông qua thành phần


10

Tôi có một lớp: Ađó là tổng hợp của một số lớp nhỏ hơn B, CD.

B, CDthực hiện các giao diện IB, ICIDtương ứng.

Kể từ khi Ahỗ trợ tất cả các chức năng của B, CD, Adụng cụ IB, ICIDlà tốt, nhưng điều này không may dẫn đến rất nhiều tái định tuyến trong việc thực hiệnA

Thích như vậy:

interface IB
{
    int Foo {get;}
}

public class B : IB
{
    public int Foo {get {return 5;}}
}

interface IC
{
    void Bar();
}

public class C : IC
{
    public void Bar()
    {
    }
}

interface ID
{
    string Bash{get; set;}
}

public class D: ID
{
    public string Bash {get;set;}
}

class A : IB, IC, ID
{
    private B b = new B();
    private C c = new C();
    private D d = new D();

    public int Foo {get {return b.Foo}}

    public A(string bash)
    {
        Bash = bash;
    }

    public void Bar()
    {
        c.Bar();
    }

    public string Bash
    {
         get {return d.Bash;}
         set {d.Bash = value;}
    }
}

Có cách nào để loại bỏ bất kỳ chuyển hướng nồi hơi này trong A? B, CDtất cả thực hiện chức năng khác nhau nhưng phổ biến, và tôi như thế Adụng cụ IB, ICIDbởi vì nó có nghĩa là tôi có thể vượt qua trong Achính nó như là một sự phụ thuộc phù hợp với những giao diện, và không cần phải tiếp xúc với các phương pháp helper bên trong.


Bạn có thể nói một chút gì đó về lý do tại sao bạn cần một lớp A để thực hiện IB, IC, ID không? Tại sao không chỉ phơi bày BCD là công khai?
Esben Skov Pedersen

Tôi nghĩ rằng lý do chính của tôi để thích Athực hiện IB, ICIDnó cảm thấy hợp lý hơn để viết Person.Walk()trái ngược với Person.WalkHelper.Walk(), ví dụ.
Nick Udell

Câu trả lời:


7

Những gì bạn đang tìm kiếm thường được gọi là mixins . Đáng buồn thay, C # không thực sự hỗ trợ những người đó.

Có một vài cách giải quyết: một , hai , ba và nhiều hơn nữa.

Tôi thực sự thực sự thích cái cuối cùng. Ý tưởng về việc sử dụng lớp một phần được tạo tự động để tạo ra bản tóm tắt có lẽ là gần nhất mà bạn có thể có được giải pháp thực sự tốt:

[pMixins] là một trình cắm thêm Visual Studio quét một giải pháp cho các lớp một phần được trang trí với các thuộc tính pMixin. Bằng cách đánh dấu một phần lớp của bạn, [pMixin] có thể tạo tệp phía sau mã và thêm thành viên bổ sung vào lớp của bạn


2

Mặc dù bản thân nó không làm giảm bản ghi trong mã, nhưng Visual Studio 2015 hiện có một tùy chọn tái cấu trúc để tự động tạo bản mẫu cho bạn.

Để sử dụng điều này, đầu tiên hãy tạo giao diện IExamplevà cách thực hiện Example. Sau đó tạo lớp mới của bạn Compositevà làm cho nó kế thừa IExample, nhưng không thực hiện giao diện.

Thêm một thuộc tính hoặc trường loại Examplevào Compositelớp của bạn , mở menu hành động nhanh trên mã thông báo IExampletrong Compositetệp lớp của bạn và chọn "Thực hiện giao diện thông qua 'Ví dụ'" trong đó 'Ví dụ' trong trường hợp này là tên của trường hoặc thuộc tính.

Bạn nên lưu ý rằng mặc dù Visual Studio sẽ tạo và chuyển hướng tất cả các phương thức và thuộc tính được xác định trong giao diện tới lớp trình trợ giúp này cho bạn, nhưng nó sẽ không chuyển hướng các sự kiện kể từ khi câu trả lời này được đăng.


1

Lớp học của bạn đang làm quá nhiều, đó là lý do tại sao bạn phải thực hiện quá nhiều chương trình soạn thảo. Bạn nói trong các ý kiến:

cảm thấy hợp lý hơn khi viết Person.Walk () trái ngược với Person.WalkHelper.Walk ()

Tôi không đồng ý. Hành động đi bộ có khả năng liên quan đến nhiều quy tắc và không thuộc về Personlớp - nó thuộc về một WalkingServicelớp với walk(IWalkable)phương thức mà Person thực hiện IWalkable.

Luôn ghi nhớ các nguyên tắc RẮN khi bạn viết mã. Hai cách được áp dụng nhiều nhất ở đây là Tách biệt các mối quan tâm (trích xuất mã đi bộ sang một lớp riêng) và Phân đoạn giao diện (chia giao diện thành các nhiệm vụ / chức năng / khả năng cụ thể). Có vẻ như bạn có thể có một số I với nhiều giao diện của mình nhưng sau đó hoàn tác tất cả công việc tốt của bạn bằng cách làm cho một lớp thực hiện chúng.


Trong ví dụ của tôi, chức năng được triển khai trong các lớp riêng biệt và tôi có một lớp bao gồm một vài trong số này như là một cách để nhóm các hành vi cần thiết. Không có triển khai thực tế nào tồn tại trong lớp lớn hơn của tôi, tất cả đều được xử lý bởi các thành phần nhỏ hơn. Có lẽ bạn đã đúng, và làm cho các lớp người trợ giúp đó công khai để họ có thể được tương tác trực tiếp với nhau là cách để đi.
Nick Udell

4
Đối với ý tưởng về một walk(IWalkable)phương pháp, cá nhân tôi không thích nó bởi vì sau đó các dịch vụ đi bộ trở thành trách nhiệm của người gọi, và không phải là Người, và tính nhất quán không được đảm bảo. Bất kỳ người gọi nào cũng sẽ phải biết sử dụng dịch vụ nào để đảm bảo tính nhất quán, trong khi việc giữ nó trong lớp Người có nghĩa là nó phải được thay đổi bằng tay để hành vi đi bộ trở nên khác biệt, trong khi vẫn cho phép đảo ngược phụ thuộc.
Nick Udell

0

Những gì bạn đang tìm kiếm là nhiều thừa kế. Tuy nhiên, cả C # và Java đều không có.

Bạn có thể mở rộng B từ A. Điều này sẽ loại bỏ sự cần thiết của một trường riêng cho B cũng như keo chuyển hướng. Nhưng bạn chỉ có thể làm điều này cho một trong B, C hoặc D.

Bây giờ nếu bạn có thể tạo C kế thừa từ B và D từ C thì bạn chỉ phải có A gia hạn D ...;) - mặc dù vậy, tôi thực sự không khuyến khích điều đó trong ví dụ này vì không có dấu hiệu nào cho nó.

Trong C ++, bạn có thể có A thừa kế từ B, C và D.

Nhưng nhiều kế thừa làm cho các chương trình khó lý luận hơn và có vấn đề riêng của nó; Hơn nữa, thường có một cách sạch sẽ để tránh nó. Tuy nhiên, đôi khi không có nó, người ta cần phải đánh đổi thiết kế giữa việc lặp lại bản tóm tắt và cách mô hình đối tượng được phơi bày.

Cảm giác giống như bạn đang cố gắng kết hợp thành phần và kế thừa. Nếu đây là C ++, bạn có thể sử dụng giải pháp kế thừa thuần túy. Nhưng vì nó không nên khuyên bạn nên nắm lấy thành phần.


2
Bạn có thể có nhiều kế thừa bằng cách sử dụng các giao diện trong cả java và c #, giống như op đã thực hiện trong mã ví dụ của mình.
Robert Harvey

1
Một số người có thể xem xét việc thực hiện một giao diện giống như nhiều kế thừa (như đã nói trong C ++). Những người khác sẽ không đồng ý, vì các giao diện không thể trình bày các phương thức cá thể kế thừa, đó là những gì bạn sẽ có nếu bạn có nhiều kế thừa. Trong C #, bạn không thể mở rộng nhiều lớp cơ sở, do đó, bạn không thể kế thừa các triển khai phương thức cá thể từ nhiều lớp, đó là lý do tại sao bạn cần tất cả các mẫu soạn sẵn ...
Erik Eidt
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.