Kompozisyon yoluyla arayüzleri uygulayan sınıftaki kazan plakasını azaltmak


11

Ben bir sınıf vardır: Aküçük sınıflar, bir dizi bir bileşimidir B, Cve D.

B, CVe Darabirimlerini IB, ICve IDsırasıyla.

Yana Atüm işlevselliği destekler B, Cve D, Auygular IB, ICve IDaynı zamanda, ama bir sürü bu maalesef potansiyel müşteri uygulanmasında yeniden yönlendirmeA

Şöyle ki:

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;}
    }
}

Bu kazan plakası yönlendirmesinden herhangi birinden kurtulmanın bir yolu var mı A? B, CVe Dtüm farklı ama ortak işlevselliği uygulamak ve bunun gibi Aaletlerin IB, ICve IDbu demektir çünkü içinde geçebilir Abu arabirimleri eşleşen bir bağımlılık olarak kendisi ve iç yardımcı yöntemleri göstermek gerekmez.


IB, IC, ID'yi uygulamak için neden A sınıfına ihtiyacınız olduğu hakkında biraz şey söyleyebilir misiniz? Neden sadece BCD'yi kamuya açıklamıyorsunuz?
Esben Skov Pedersen

1
Ben tercih için birincil nedeni düşünmek Auygulamak IB, ICve IDo yazma daha mantıklı hissediyor olduğunu Person.Walk()aksine Person.WalkHelper.Walk()örneğin.
Nick Udell

Yanıtlar:


7

Aradığınıza yaygın olarak mixins denir . Ne yazık ki, C # bunları doğal olarak desteklemiyor.

Birkaç geçici çözüm vardır: bir , iki , üç ve daha fazlası.

Aslında sonuncuyu gerçekten çok seviyorum. Isı levhasını oluşturmak için otomatik olarak oluşturulan kısmi sınıfı kullanma fikri, muhtemelen iyi bir çözüme ulaşabileceğiniz en yakın fikirdir:

[pMixins], pMixin öznitelikleriyle dekore edilmiş kısmi sınıflar için bir çözümü tarayan bir Visual Studio eklentisidir. Sınıfınızı kısmi olarak işaretleyerek, [pMixins] kod arkasında bir dosya oluşturabilir ve sınıfınıza ek üyeler ekleyebilir


2

Kodun kendisinde kaynak plakasını azaltmasa da, Visual Studio 2015 artık sizin için otomatik olarak ısıtıcı plakası oluşturmak için bir yeniden düzenleme seçeneği ile birlikte geliyor.

Bunu kullanmak için önce arayüzünüzü IExampleve uygulamanızı oluşturun Example. Ardından yeni sınıfınızı oluşturun Compositeve devralın IExample, ancak arabirimi uygulamayın.

Türünde bir özelliği veya alan ekleme Examplesizin için Composite, sınıf belirteci üzerindeki hızlı İşlemler menüsünü açmak IExampleiçin de Compositesınıf dosyası ve " 'Örnek' yoluyla arabirimini uygular" seçeneğini bu durumda 'Örnek' alanın veya özelliğin adıdır.

Visual Studio oluşturmak ve sizin için bu yardımcı sınıfına arabiriminde tanımlanan tüm yöntemleri ve özellikleri yönlendirir olurken, bu unutmayın gerekir değil Bu cevap yayınlanmıştır zaman gibi olayları yönlendirir.


1

Sınıfınız çok fazla şey yapıyor, bu yüzden çok fazla kazan plakası uygulamanız gerekiyor. Yorumlarda söylersiniz:

Person.WalkHelper.Walk () yerine Person.Walk () yazmak daha mantıklı geliyor

Katılmıyorum. Yürüme eyleminin birçok kuralı içermesi muhtemeldir ve Personsınıfa ait değildir - Kişinin uyguladığı WalkingServicebir walk(IWalkable)yöntemle bir sınıfa aittir IWalkable.

Kod yazarken daima SOLID ilkelerini unutmayın. Burada en uygun olan ikisi Endişelerin Ayrılması (yürüyüş kodunu ayrı bir sınıfa çıkartın) ve Arayüz Ayrımı (arayüzleri belirli görevlere / işlevlere / yeteneklere ayırın). Birden fazla arayüzünüzle bazı I'lere sahip olabileceğiniz gibi görünüyor, ancak daha sonra bir sınıfı bunları uygulayarak tüm iyi çalışmalarınızı geri alıyorlar.


Benim örnekte işlevselliği olan ayrı sınıflara uygulanan ve ben gerekli davranışı gruplama bir yolu olarak bunlardan birkaç oluşan bir sınıf var. Daha büyük sınıfımda gerçek uygulamaların hiçbiri yok, hepsi daha küçük bileşenler tarafından işleniyor. Belki de haklısınız ve bu yardımcı sınıfları doğrudan etkileşimde bulunabilmeleri için herkese açık hale getirmenin yolu budur.
Nick Udell

4
Bir walk(IWalkable)yöntem fikrine gelince , kişisel olarak beğenmedim çünkü o zaman yürüyüş hizmetleri Kişinin değil, arayanın sorumluluğuna dönüşür ve tutarlılık garanti edilmez. Herhangi bir arayan, tutarlılığı garanti etmek için hangi hizmeti kullanacağını bilmek zorundayken, bunu Person sınıfında tutmak, bağımlılığın tersine çevrilmesine izin verirken yürüme davranışının farklı olması için manuel olarak değiştirilmesi gerektiği anlamına gelir.
Nick Udell

0

Aradığın şey çoklu miras. Ancak, ne C # ne de Java'da yoktur.

B'yi A'dan uzatabilirsiniz. Bu, B için özel bir alan ve yönlendirme tutkalı ihtiyacını ortadan kaldıracaktır. Ancak bunu yalnızca B, C veya D'den biri için yapabilirsiniz.

Şimdi C'yi B'den ve D'yi C'den devralabilirseniz, o zaman sadece A exture D'ye sahip olmanız gerekir ...;) onun için.

C ++ 'da A, B, C ve D'den miras alabilirsiniz.

Ancak çoklu miras, programları akıl yürütmeyi zorlaştırır ve kendi sorunları vardır; Ayrıca, bundan kaçınmak için genellikle temiz bir yol vardır. Yine de, bazen onsuz, tekrarlanan kazan plakası ile nesne modelinin nasıl ortaya çıktığı arasında tasarım ödünleşmeleri yapılması gerekir.

Kompozisyonu ve mirası karıştırmaya çalıştığınız hissi veriyor. Bu C ++ olsaydı, saf bir miras çözümü kullanabilirsiniz. Ama olmadığından kompozisyonu benimsemenizi tavsiye ederim.


2
Op'un örnek kodunda yaptığı gibi, hem java hem de c # arayüzlerini kullanarak birden fazla mirasa sahip olabilirsiniz.
Robert Harvey

1
Bazıları çoklu kalıtımla aynı arabirimi uygulamayı düşünebilir (C ++ 'da olduğu gibi). Diğerleri aynı fikirde değildir, çünkü arayüzler devralınabilir örnek yöntemleri sunamaz, bu da birden fazla devralmanız varsa sahip olacağınız şeydir. C # 'da, birden fazla temel sınıfı genişletemezsiniz, bu nedenle birden fazla sınıftan örnek yöntemi uygulamalarını devralamazsınız, bu nedenle tüm ortak
plakaya

Çoklu kalıtımın kötü olduğunu kabul ediyorum, ancak C # / Java'nın çoklu arayüz uygulamasıyla tek kalıtım alternatifi bir çözüm değil ( arayüz iletme olmadan ergonomik bir kabus). Şimdi Golang ile biraz zaman geçirdikten sonra, Go'nun herhangi bir mirasa sahip olmama ve tamamen arayüz iletme ile kompozisyona güvenme konusunda doğru fikre sahip olduğunu düşünüyorum - ancak özel uygulamalarının da sorunları var. En iyi çözümün (henüz kimse uygulanmadığı görülüyor), herhangi bir türü bir arabirim olarak kullanma yeteneğine sahip, yönlendirme ile kompozisyon olduğunu düşünüyorum .
Dai
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.