Когда несколько классов реализуют один (или более) интерфейс, несмотря на то, что они являются разными классами, они могут иметь много общей логики и лишь незначительно отличаться.
В этом случае может быть удобно переместитьобщая логика в общий класс, который затем используется в качестве компонента.Вызовы методов с общей логикой делегируются этому компоненту.
Например:
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...
В классах FooBarBaz1
и FooBarBaz2
мы полностью переносим экземпляр DefaultFoo
всоздайте у общественности впечатление, что FooBarBaz1
и FooBarBaz2
выполняют работу, а просто делегируют ее.
Проблема в том, что если у вас есть большое количество классов, которые должны реализоватьИнтерфейс и / или интерфейс имеет много методов, в результате вы вынуждены написать много «бесполезного» кода делегирования.
Поэтому мой вопрос: разве мы НЕ можем просто НЕ обернуть разделяемую логику?? Вместо того, чтобы требовать реализации методов, интерфейсы требуют, чтобы эти компоненты были доступны.
Вместо этого мы бы:
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 #, но я думаю, что это также применимо к некоторым другим языкам.