使用合成时,我们真的需要包装组件吗?

时间:2018-09-28 17:23:14

标签: c# interface traits composition

当多个类实现一个(或多个)接口时,尽管它们是不同的类,但它们可能有很多共同的逻辑,只是略有不同。

在这种情况下,将共享逻辑移到共享类中然后将其用作组件可能会很方便。具有共享逻辑的方法调用将委托给该组件。

例如:

interface IFoo
{
    void DoFoo();
}

interface IBar
{
    void DoBar();
}

interface IBaz
{
    void DoBaz();
}

class DefaultFoo()
{
    public void Do() { /* Shared logic */ }
}

class DefaultBar()
{
    public void Do() { /* Shared logic */ }
}

class FooBarBaz1 : IFoo, IBar, IBaz
{
    DefaultFoo defaultFoo = new DefaultFoo();
    DefaultBar defaultBar = new DefaultBar();

    public void DoFoo() { defaultFoo.Do(); }
    public void DoBar() { defaultBar.Do(); }
    public void DoBaz() { /* FooBarBaz1 specific IBaz implementation */ }
}

class FooBarBaz2 : IFoo, IBar, IBaz
{
    DefaultFoo defaultFoo = new DefaultFoo();

    public void Foo() { defaultFoo.Do(); }
    public void Bar() { /* FooBarBaz2 specific IBar implementation */ }
    public void Baz() { /* FooBarBaz2 specific IBaz implementation */ }
}

// More ForBarBazX classes...

在类FooBarBaz1FooBarBaz2中,我们完全包装了DefaultFoo实例,以给公众一种印象,FooBarBaz1FooBarBaz2在做他们只是委派工作时工作。

问题是,如果您有许多必须实现该接口的类和/或该接口具有许多方法,那么最终将不得不编写许多“无用的”委托代码。

所以我的问题是:我们不能不包装共享逻辑吗?除了要求实现方法之外,接口还要求公开这些组件。

我们将改为:

interface IFoo
{
    DefaultFoo Foo { get; }
}

interface IBar
{
    DefaultBar Bar { get; }
}

interface IBaz
{
    DefaultBaz Baz { get; }
}

class DefaultFoo()
{
    public virtual void Do() { /* Shared logic */ } // Note the virtual.
}

class DefaultBar()
{
    public virtual void Do() { /* Shared logic */ } // Note the virtual.
}

class FooBarBaz1 : IFoo, IBar, IBaz
{
    private class SpecificBaz : DefaultBaz
    {
        public override void DoBaz() { /* Specific logic */ }
    }

    public DefaultFoo Foo { get; private set; }
    public DefaultBar Bar { get; private set; }
    public DefaultBaz Baz { get; private set; }

    public FooBarBaz1()
    {
        Foo = new DefaultFoo();
        Bar = new DefaultBar();
        Baz = new SpecificBaz();
    }
}

class FooBarBaz2 : IFoo, IBar, IBaz
{
    private class SpecificBar : DefaultBar
    {
        public override void Bar() { /* Specific logic */ }
    }

    private class SpecificBaz : DefaultBaz
    {
        public override void Baz() { /* Specific logic */ }
    }

    public DefaultFoo Foo { get; private set; }
    public DefaultBar Bar { get; private set; }
    public DefaultBaz Baz { get; private set; }

    public FooBarBaz1()
    {
        Foo = new DefaultFoo();
        Bar = new SpecificBaz();
        Baz = new SpecificBaz();
    }
}

比,而不是:

ForBarBaz1 fooBarBaz = new ForBarBaz1();
fooBarBaz.Foo();
fooBarBaz.Bar();
fooBarBaz.Baz();

一个人将访问暴露的组件:

ForBarBaz1 fooBarBaz = new ForBarBaz1();
fooBarBaz.Foo.Do();
fooBarBaz.Bar.Do();
fooBarBaz.Baz.Do();

您对此有何看法?似乎它在保留模块化的同时又避免了大量的“无用”包装代码。

PS:我要的是C#,但我想它也适用于其他一些语言。

0 个答案:

没有答案