Как лучше решить проблему наличия сущности с зависимостями службы в API-подобной системе? - PullRequest
3 голосов
/ 29 февраля 2012

Я создал несколько оберток вокруг java.lang.reflect классов: JavaClass упаковка Class<?>, JavaMethod упаковка Method, JavaConstructor упаковка Constructor<?>, и так далее.

У каждого из них есть множество добытчиков вокруг некоторых свойств, заданных их java.lang.reflect аналогами.

Каждый из классов-оболочек также предоставляет набор методов, которые делают сложные вычисления, и они являются основной причиной создания этих классов-оболочек вместо использования исходных.

С учетом, например, JavaClass.getMethods():

/**
 * Gets us the list of all methods in the class. Includes all the methods
 * defined in the current class plus all the inherited methods.
 */
public Set<IJavaMethod> getMethods() {
    Set<IJavaMethod> javaMethods = new HashSet<IJavaMethod>();

    for (Constructor<?> constructor : clss.getConstructors())
        javaMethods.add(JavaFactory.createJavaMethod(constructor));

    for (Method method : clss.getMethods())
        javaMethods.add(JavaFactory.createJavaMethod(method));

    return javaMethods;
}

Обратите внимание на использование статического JavaFactory класса. Этот класс является фабрикой из множества JavaXXX видов классов. Я хотел превратить этот статический класс в класс методов экземпляра, но это поставит проблему необходимости передавать в эту сущность сервис.

Кроме того, это создаст проблему со следующими открытыми статическими переменными:

JavaClass, например, имеет набор открытых статических классов, которые обычно используются в моей системе:

public class JavaClass implements IJavaType {
    private final Class<?> clss;

    public static final JavaClass VOID = new JavaClass(void.class);
    public static final JavaClass BOOLEAN = new JavaClass(boolean.class);
    public static final JavaClass STRING = new JavaClass(String.class);
    public static final JavaClass OBJECT = new JavaClass(Object.class);
    public static final JavaClass INTEGER = new JavaClass(int.class);

       ...
}

Я мог бы «решить» проблему, если бы этот метод был в другом классе, JavaClassHelper, но иметь JavaClass без возможности простого доступа к методам, по крайней мере, неудобно. Причина, по которой JavaClass нужен JavaFactory, заключается в том, что ему постоянно нужно направлять данные из мира java.lang.reflect в мои оболочки. JavaFactory - не единственный случай зависимости JavaClass. У меня есть еще пара методов, которые также интенсивно используют некоторые другие сервисы, хотя, поскольку у них есть пустой конструктор, автор кода решил просто создать их экземпляр прямо на месте.

Как смоделировать это? Теоретически, идея просто взять все услуги из JavaClass кажется асом, но в реальном мире это кажется немного непрактичным, в смысле дружественного API. Другая идея состояла бы в том, чтобы службы передавались через конструктор и создавали только экземпляры JavaXXX классов через JavaFactory, скрывая для всего мира все эти вопросы.

1 Ответ

2 голосов
/ 08 марта 2012

Если вам действительно нужно использовать фабрику для создания экземпляров экземпляров JavaConstructor и JavaMethod и вы хотите избежать статических ссылок, тогда вам нужно использовать механизм поставщика услуг Java .

Тем не менее, я думаю, что основной причиной проблемы здесь является использование фабричного шаблона в первую очередь.

По моему опыту, лучше устранить причину, а не симптомы.

Какую выгоду фабрика предоставляет по сравнению с прямыми вызовами конструктора JavaConstructor и JavaMethod?

Поскольку getMethod уже выполняет переключение между конструкторами и методами, переключение, предоставляемое перегруженным методом JavaFactory.createJavaMethod, по-видимому, не дает никаких преимуществ. Очевидно, что методы JavaFactory.createJavaMethod просто вызывают конструкторы их соответствующих возвращаемых типов? Так почему бы не потерять фабричный шаблон, просто сначала создайте объекты непосредственно через их конструкторы, и у вас останется что-то вроде этого:

public class JavaClass 
{      
  ...

  /**
   * Gets us the list of all methods in the class. Includes all the methods
   * defined in the current class plus all the inherited methods.
   */
  public Set<IJavaMethod> getMethods() 
  {
    Set<IJavaMethod> javaMethods = new HashSet<IJavaMethod>();

    for (Constructor<?> constructor : clss.getConstructors()) 
    {
      javaMethods.add(new JavaConstructor(constructor));
    }

    for (Method method : clss.getMethods())
    {
      javaMethods.add(new JavaMethod(method));
    }

    return javaMethods;
  }

  ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...