Нет абсолютно правильного ответа на ваш вопрос. И не нужно искать тот. На самом деле, что нужно понимать при разработке архитектуры для некоторого программного обеспечения: если вы не знаете, что правильно - просто используйте абстракцию. Тогда, если вы в конце концов поймете, что ваша первоначальная реализация была неправильной, вы просто замените ее на другую, и вам не придется менять публичный интерфейс.
Я имею в виду, что в вашем случае это не очевидно: с одной стороны вы должны использовать одноэлементный экземпляр, поэтому не нужно создавать много экземпляров, потреблять больше памяти и вносить дополнительные издержки при создании объекта. Однако, с другой стороны, вы не можете быть уверены, что требования вашего проекта не изменятся - возможно, вам придется добавить какое-то состояние к вашей WebBrowserUtility
услуге и выполнить несколько вызовов параллельно, сохраняя разные состояния для разных потребителей, или Вы можете даже реализовать пул экземпляров для своего класса. Вы не можете предсказать будущее, поэтому вы должны использовать абстракцию.
Самый простой способ абстрагировать создание объекта - это использовать статический фабричный метод и назвать его как getInstance()
- точно так же, как если вы собираетесь реализовать синглтон, хотя и не думайте об этом только с точки зрения одноэлементной реализации - это скорее просто абстракция того, как его реализовать. На данный момент вы можете придерживаться singleton, так что этот метод всегда будет возвращать единственный экземпляр службы, хотя в будущем, если вам потребуется изменить способ создания класса, вы просто измените реализацию getInstance()
без необходимости изменять какие-либо код, который на самом деле использует ваш сервис. Так что вам не придется решать, какой путь лучше, пока у вас не будет достаточно информации для выбора.
Таким образом, создание экземпляров ваших служб с помощью фабричных методов дает вам больше гибкости, однако есть и лучшие способы. Если вы продолжите развивать эту идею об абстракции экземпляра, вы поймете, что обычно вы хотите переместить код создания из фактического сервиса в выделенный фабричный класс , потому что иногда вы хотите создать один и тот же сервис в другом пути для разных средств. Дальнейшее развитие этой идеи заканчивается использованием шаблона Inversion of Control , который является окончательным ответом о том, как создавать экземпляры ваших служб и управлять зависимостями между ними.
Если вы используете Java, взгляните на очень популярную Spring Framework , которая позволяет вам определять правила создания сервисов в файле конфигурации, поэтому, если вам нужен прототип вместо синглтона, это только вопрос изменения этого конфигурационного файла.
Я бы также не рекомендовал реализовывать ваш класс обслуживания как набор статических методов с необходимой логикой. Причина этого - это может быть просто и быстро реализовать это прямо сейчас, однако в будущем ваши руки будут связаны с интерфейсом, который определяет статические методы. Поэтому, если вам в конечном итоге потребуется использовать несколько экземпляров, вам придется изменить код потребителей, который также использует ваши статические методы, потому что статические сигнатуры находятся в вашем интерфейсе, а не только в вашей реализации. В отличие от этого, выбор между прототипом / синглтоном скрыт в коде создания экземпляра, поэтому потребителям все равно, как создается экземпляр, - они просто запрашивают экземпляр и получают его.