Альтернатива статическим классам и методам Util в Java - PullRequest
3 голосов
/ 23 сентября 2019

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

public String formatCustomerSet(final Set<Customer> customers) {
    String result = "";
    for (Customer customer : customers) {
        result += customer.getFirstName() + " : " + customer.getLastName() + "\n";
    }

    return result;
}

Я использую этот код в нескольких классах.Теперь, где я должен положить это?Я обнаружил, что классы утилит следует избегать и не должны использоваться?https://lostechies.com/chrismissal/2009/06/01/anti-patterns-and-worst-practices-utils-class/

Тогда должен ли использоваться класс Util с определенным именем, например CustomerFormatter, или из него следует создать класс ООП?Какой из них рекомендуется и почему?

Я использую этот код в нескольких классах.Теперь, где я должен положить это?Я обнаружил, что классы утилит следует избегать и не должны использоваться?https://lostechies.com/chrismissal/2009/06/01/anti-patterns-and-worst-practices-utils-class/

Тогда должен ли использоваться класс Util с определенным именем, например CustomerFormatter, или из него следует создать класс ООП?Какой из них рекомендуется и почему?

Ответы [ 3 ]

1 голос
/ 23 сентября 2019

Я не согласен с тем, что утилит следует избегать.Прекрасно иметь класс, содержащий статические методы, которые являются чисто служебными.Иногда функции или операции должны быть просто функциями или операциями.Не всегда есть необходимость связывать их с каким-либо абстрактным типом объекта или чем-то еще.

Однако я согласен с тем, что при создании утилитных классов вы должны строго определять, какие типы утилит будут предоставленыкласс.Если у вас есть набор статических методов, связанных с выполнением математических операций, вы можете создать класс утилит ExtendedMath.Если вы много занимаетесь математикой и класс становится слишком толстым, попробуйте улучшить его.Сгруппируйте их по типу математики, например Algebra и Vector.

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

В вашем случае вы должны задать себе вопрос: «Хочу ли я создать жесткую зависимость?моего кода для реализации formatCustomerSet? "Если вы на 100% уверены, что вы всегда будете форматировать наборы клиентов одним и тем же способом, и вам никогда не понадобятся другие средства форматирования, тогда может быть целесообразно использовать статический метод.Если нет, то, возможно, лучше поместить его в класс CustomerSetFormatter как нестатическую функцию.

Я не могу дать вам ответ «да» или «нет», так как вам нужно взвесить «за» и «против».вы сами.Просто примите во внимание следующее:

  • Когда вы ссылаетесь на статический метод, вы создаете жесткую зависимость для этого статического метода.Иногда это нормально, иногда нет.Основным принципом разработки программного обеспечения является повторное использование .Можете ли вы повторно использовать код, который вызывает статическую функцию, также и в других контекстах?Или статическая функция слишком специфична для контекста?
  • Другой основной принцип программирования - внедрение зависимостей .Допустим, у вас есть Class A, который требует клиентского форматера.Что вы могли бы сделать, это вы можете сделать interface CustomerFormatterClass A вы затем определяете конструктор: A(CustomerFormatter formatter).Это позволяет вам повторно использовать Class A при использовании различных реализаций CustomerFormatter.Это значительно увеличивает возможность повторного использования Class A.При использовании статических функций это больше невозможно.
  • Общие общие операции (такие как функции, определенные в Math, например, min(), max(), ceil() или floor()) полностьюгарантированно быть статическими функциями.Они делают то, что обычно используется, и только одно.Как правило, вы можете использовать такие функции в качестве примера, когда статический метод полностью оправдан.
  • Является ли ваша функция чистой функцией ?Это функция, которая всегда дает точно такой же вывод для любого уникального ввода.Последующие вызовы к одним и тем же функциям всегда будут приводить к одному и тому же результату, если входные данные остаются неизменными.Если дело обстоит так, тогда может быть прекрасно сделать ваш метод статичным.Если это не так, и последующие вызовы одной и той же функции дают разные выходные данные в зависимости от некоторого произвольного состояния или вызовов, которые были сделаны ранее, то вам следует рассмотреть возможность сделать его нестатичным.Создание статических функций, которые обеспечивают разные выходы для одного и того же входа, поскольку они зависят от некоторого состояния, обычно рассматривается как анти-шаблон .

Надеюсь, это немного вам поможет.

1 голос
/ 23 сентября 2019

Используя потоки Java, вы можете получить то, что вы хотите, с помощью следующей однострочной строки (при условии, что в классе Customer есть хороший toString()):

String result = 
    customers.stream().map(Customer::toString).collect(Collectors.joining("\n"));

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

Редактировать (ответить на комментарий) : Да, я быначнем с создания этого статического метода в классе Customer, поскольку он действительно не использует никаких полей в этом классе.

Редактирование 2 (примечание): Кстати, если вы хотитечтобы использовать метод в вашем вопросе, рассмотрите возможность использования StringBuilder вместо String.

0 голосов
/ 23 сентября 2019

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

Недостаток утилиты /статические классы: Основная проблема в том, что класс, зависящий от статического метода из класса утилит, имеет тесную связь

  1. Тестирование немного сложнее: поскольку у вас жесткая зависимость от класса Util, вы не можете легко обеспечить фиктивную реализацию.
  2. Инверсия управления: внедрение зависимостей невозможно при использовании классов утилит.
  3. Прокси-функции: многие фреймворки зависят от динамических прокси-серверов для добавления дополнительной функциональности в экземпляры классовНапример, уровень ведения журнала, который невозможен для служебных классов.
  4. Одна ответственность: Со временем, если вы не очень строги, эти классы, как правило, накапливают все больше и больше кода, который может быть не так связан соригинальные методы.Класс потеряет свою первоначальную ответственность.

Ссылка: https://www.vojtechruzicka.com/avoid-utility-classes/

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