Есть ли что-нибудь плохо в объявлении вложенного класса в интерфейсе в Java?

У меня есть интерфейс ProductService с методом findByCriteria. Этот метод имел длинный список nullable параметров, как productName, maxCost, minCost, producer и так далее.

Я осуществил рефакторинг этот метод путем представления Объекта параметра. Я создал класс SearchCriteria и теперь сигнатура метода похожа на это:

findByCriteria (SearchCriteria criteria)

Я думал это экземпляры SearchCriteria только создаются вызывающими сторонами метода и только используются внутри findByCriteria метод, т.е.:

void processRequest() {
   SearchCriteria criteria = new SearchCriteria ()
                                  .withMaxCost (maxCost)
                                  .......
                                  .withProducer (producer);

   List products = productService.findByCriteria (criteria);
   ....
}

и

List findByCriteria(SearchCriteria criteria) {
    return doSmthAndReturnResult(criteria.getMaxCost(), criteria.getProducer());    
}

Таким образом, я не хотел создавать отдельный общедоступный класс для SearchCriteria и вставленный это ProductServiceInterface:

public interface ProductService {
    List findByCriteria (SearchCriteria criteria);

    static class SearchCriteria {
       ...
    }
}

Есть ли что-нибудь плохо с этим интерфейсом? Куда Вы поместили бы SearchCriteria класс?

10
задан Roman 24 May 2010 в 11:48
поделиться

4 ответа

Я думаю, это неплохо выглядит. Это ясно указывает на то, что SearchCriteria предназначен для использования с ProductService s.

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

3
ответ дан 4 December 2019 в 02:49
поделиться

Я бы посоветовал вам использовать классы, когда у вас есть методы, которые могут требовать более или менее обнуляемых аргументов; он дает вам возможность предоставить все, что вам нужно, без необходимости вызывать такой метод, как:

someMethod("foo", null, null, null, null, null, null, ..., "bar");

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

someMethod(new ObjParam().setFoo("foo").setBar("bar"));

Второй метод является одноразовым и многоразовым (без множества переопределений методов ). И я не говорю здесь, что переопределение метода - это плохо! Наоборот. Однако со многими необязательными аргументами я бы предпочел второй вызов.

Что касается внутренних классов, они иногда полезны, но я лично следую этим рекомендациям:

  1. старайтесь использовать внутренние классы только тогда, когда внутренний класс должен быть закрытым (например: в случае пользовательской реализации LinkedList, Класс узла является частным классом и поэтому является внутренним классом.)
  2. обычно, только если класс не может использоваться повторно и используется в основном в (очень) небольшой группе классов, я сделаю его внутренним классом
  3. " родительский "и внутренний класс становится достаточно большим; тогда обоим классам предоставляется собственный исходный файл Java для удобства чтения, если только внутренний класс не должен быть частным, как в первом пункте.

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

2
ответ дан 4 December 2019 в 02:49
поделиться

Это неплохо и может быть полезно, если вы хотите более плотную группировку между интерфейсами и некоторыми вспомогательными объектами, такими как компараторы. (Я сделал то же самое с интерфейсом и внутренними классами, предоставляющими полезные компараторы, которые сравнивают экземпляры интерфейса.)

это может быть немного неудобно для клиентов, поскольку они должны префикс имени внутреннего класса с помощью имя интерфейса (или используйте статический импорт), но хорошая IDE позаботится об этом за вас (но код может быть приправлен объявлениями Interface.SomeClass , что выглядит не очень хорошо.)

Однако в конкретном случае SearchCriteria выглядит не столь тесно связанным с интерфейсом, поэтому его можно использовать как обычный класс пакета.

2
ответ дан 4 December 2019 в 02:49
поделиться

Боюсь, я хочу проголосовать за плохое. В любом случае, довольно плохо, можно делать и похуже ...

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

Что еще более важно, разделение делает код задействованных сущностей проще и эффективнее. явный. Для меня это перекрывает все другие проблемы (ах, кроме правильного кода, конечно). Я считаю, что простота и ясность наиболее полезны, когда дело касается сохранения моих волос или, по крайней мере, тех, кто будет ухаживать за ними ...

0
ответ дан 4 December 2019 в 02:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: