Принцип разделения интерфейса - Как вызвать метод, определенный в отдельном интерфейсе? - PullRequest
0 голосов
/ 12 января 2019

Итак, у нас был интерфейс, который существует уже давно. Давайте назовем это IFoo. В нем определено много методов, и его реализуют около 10 классов.

Все время, когда нам нужно было создать экземпляр одного из этих классов, мы использовали простой шаблон фабрики:

IFoo foo = FooFactory.Create(...);

Тогда, конечно, у нас есть доступ ко всем методам, определенным в IFoo:

foo.Method1();
foo.Method2();
etc.

Но теперь у нас есть некоторые методы, которые должны быть в некоторых из десяти классов, но не во всех. Таким образом, в соответствии с принципом разделения интерфейсов, я понимаю, что мы должны создать новый интерфейс: IBar.

Так что классы, которым нужны методы, которые будут определены в IBar, будут выглядеть так:

public class something: IFoo, IBar
{
     ...
}

Пока все хорошо. Но я не уверен, как получить доступ к этим методам. Потому что, когда мы используем тот же метод фабрики:

IFoo foo = FooFactory.Create(...);

foo не имеет методов из IBar.

Фабричный метод выглядит следующим образом (это упрощенная версия, чтобы упростить этот пост):

public static IFoo Create(string className)
{
     Type type = Type.GetType(className);
     return (IFoo)Activator.CreateInstance(type);
}

Так или иначе, мне неясно, как изменить все это, чтобы иметь доступ и к методам в IBar.

Ответы [ 2 ]

0 голосов
/ 12 января 2019

Если вы просто попытаетесь использовать преобразование типов , ваш код не будет устойчив к изменениям и может сломаться во время рефакторинга . Чтобы выбрать решение, нужно ответить на следующие вопросы:

  • Что такое IFoo и IBar? Почему вы разделяете эти интерфейсы и когда они должны использоваться? Это вопросы о мотивации использования принципа разделения интерфейса . Если у вас есть 2 действительно разных варианта использования, это нормально, но вы не должны использовать его только для соблюдения правил. Это нормально, чтобы иметь интерфейс со многими методами. если вы решите, что IFoo и IBar на самом деле являются одним интерфейсом, просто объедините их с IFooBar интерфейсом.
  • OK. Мы решили, что у нас действительно есть два интерфейса. Следующий вопрос: почему класс Something реализует оба этих интерфейса? Это нарушает Принцип единой ответственности ? Если это так, то вам нужно разделить этот класс на class Foo : IFoo и class Bar : IBar и создать новую фабрику для класса Bar, чтобы использовать ее в случаях, когда вам нужно вызвать BarMethod(). Возможно, у вас проблема с дублированным кодом или проблема с повторным использованием общих ресурсов.
  • Если у вас есть проблема с дублирующимся кодом, просто используйте наследование для ее решения.
    public class SomeBase { /* common code */ }
    public class Foo : SomeBase, IFoo { /* IFoo impementation */ }
    public class Bar : SomeBase, IBar { /* IBar impementation */ }
  • Если у вас есть проблема с повторным использованием общих ресурсов, вы можете решить ее с помощью внедрение зависимости . Например, вы добавите BarFactory, а оба FooFactory и BarFactory будут использовать SharedResourceRepository, который хранит и разрешает доступ к общим ресурсам. Если вы используете IoC-контейнер, то проблема решается его настройкой.
  • OK. Мы решили, что у нас действительно один класс. Следующий вопрос: зачем вам нужно извлекать экземпляр IFoo, чтобы использовать его методы IBar? Это определенно нарушает объектно-ориентированный дизайн, и каждое решение будет только взломать. Вы должны создать BarFactory и решить проблему с одним экземпляром с помощью Singletone , IoC-контейнеров и так далее.
0 голосов
/ 12 января 2019

Прямой метод грубой силы

 IFoo foo = FooFactory.Create(...);

 if (foo is IBar)
 {
     var b = (Ibar)foo;
     b.Barmethod();
 }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...