Как отменить зависимость для класса Factory перенесена в библиотеку

Следующий код работает очень хорошо, когда все участвующие классы находятся в одном проекте (determineSubClass является членом BaseClass):

protected static BaseClass determineSubClass(String p1, int p2, Boolean p3) {

    BaseClass baseObj = null;
    if ( (baseObj = SubClassOne.ofType(p1, p2, p3)) != null )
      return baseObj;
    else if ( (baseObj = SubClassTwo.ofType(p1, p2, p3)) != null )
      return baseObj;
    else if ( (baseObj = SubClassThree.ofType(p1, p2, p3)) != null )
      return baseObj;
    else if ( (baseObj = SubClassFour.ofType(p1, p2, p3)) != null )
      return baseObj;
    else
      return new SubClassDefault(p1, p2, p3);
}

Но теперь я хочу переместить BaseClass в общий библиотечный проект, в котором SubClassOne, SubClassTwo, SubClassThree а также SubClassFour определяются не в библиотеке, а в приложениях, использующих эту библиотеку.

Я мог бы, конечно, двигаться BaseClass вернуться к каждому приложению, использующему эту библиотеку, но мне интересно:

  • Есть ли лучшее решение?
  • Есть ли решение, которое позволило бы мне сохранить BaseClass в проекте библиотеки и избавить его от необходимости знать обо всех производных от него суперклассах?

РЕДАКТИРОВАТЬ (отвечая на вопрос @ahmet Alp Balkan ниже):

ofType() каждого подкласса делает 2 вещи:

  1. Определяет, основываясь на содержимом строки p1 и других параметров p2 и p3, имеет ли подкласс, который должен быть создан, его тип.
  2. Если ответ положительный, он создает объект подкласса self. В противном случае возвращает ноль.

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

Кстати, благодаря вашему вопросу я заметил ужасную опечатку в своем оригинальном сообщении: "SuperClassOne" должен быть "SubClassOne" и т. Д.

2 ответа

Решение

Ваша статика determineSubClass Метод является заводским методом. Очевидно, он не должен находиться на BaseClass, поскольку не только базовый класс не должен ничего знать о подклассах, но в вашем случае он ничего не может знать об этом, поскольку вы хотите найти базовый класс в другом проекте. Нет, этот метод должен находиться в фабричном классе, который отвечает за создание BaseClass экземпляров. Что вы должны сделать, это определить интерфейс (или базовый тип) для создания BaseClass экземпляры рядом с BaseType и определяет реализацию в корне композиции вашего приложения. Когда у вас есть несколько приложений, они, вероятно, имеют разные наборы BaseClass подтипы, поэтому у каждого приложения будет свой завод. Когда у вас есть эта конструкция, вы можете вводить фабрику в классы, которые нуждаются BaseClass экземпляров.

Это может выглядеть примерно так:

// Shared library
public interface IBaseClassFactory
{
    BaseClass CreateNew(String p1, int p2, Boolean p3);
}

public abstract class BaseClass
{
}

// Application code
public class SubClassOne : BaseClass
{
}

public class SubClassTwo : BaseClass
{
}

// Note that this consumer depends on IBaseClassFactory.
public class SomeConsumer
{
    private IBaseClassFactory baseClassFactory;

    public SomeConsumer(IBaseClassFactory factory)
    {
        this.baseClassFactory = factory;
    }

    public void Consume()
    {
        BaseClass instance = this.baseClassFactory
            .CreateNew("foo", 0, false);

        // use instance
    }
}  

// Composition root
class BaseClassFactory : IBaseClassFactory
{
    public BaseClass CreateNew(String p1, int p2, Boolean p3)
    {
        BaseClass baseObj = null;

        if ((baseObj = SubClassOne.ofType(p1, p2, p3)) != null)
           return baseObj;
        // etc
        else
            return new SubClassDefault(p1, p2, p3);
    }
}

Это не очень хорошая практика, что базовый класс знает о своих суперклассах. Это нарушает примерно половину принципов ОО;).....

Я бы переместил метод в новый класс с именем HierarchyManager или что-то в этом роде, и у меня был бы этот метод. Вы могли бы даже построить некоторую иерархию там -> вы могли бы эффективно сделать этот метод "расширяемым" ....

Например, в библиотеке вы можете иметь:

BaseClass -> A, B (подклассы A, B BaseClass) и некоторый LibraryHierachyManager, обрабатывающий эти три класса...

а затем в приложении, используя его:

C, D (подклассы BaseClass или A или B)

и некоторые ApplicationHieararchyManager делают:

public static BaseClass determineSubClass(String p1, int p2, Boolean p3) {
    if (baseObj = C.ofType(.....) { 
    ....


    } else {
      return LibraryHierarchyManager.determineSubClass(p1,p2, p3);
    }
}
Другие вопросы по тегам