Фабрика используется, когда у вас может быть много разных реализаций одного и того же интерфейса, и только во время выполнения определяется, какая именно клиенту нужна на самом деле. Однако клиенту не нужно знать, какую реализацию он на самом деле использует. Вот тут-то и вступает Factory: она инкапсулирует детали создания конкретного объекта и возвращает его как общую реализацию требуемого интерфейса.
На самом деле с именем Фабрики связаны два разных шаблона: Абстрактная Фабрика и Фабричный Метод . Последний используется для создания экземпляров одного продукта, а первый - для создания целого семейства связанных продуктов.
Типичным примером Abstract Factory является создание семейства виджетов в среде GUI. Клиентам платформы может потребоваться только знать, что они имеют дело с окном, или строкой состояния, или кнопкой; однако их не нужно привязывать к факту, является ли данный виджет на самом деле виджетом для Windows или MacOS. Это позволяет создавать клиентов, которые могут работать на любой из этих платформ; и теоретически, когда фреймворк переносится на новую платформу, скажем, Linux, все, что нужно, это реализовать новую фабрику, которая производит все специфичные для Linux виджеты, и подключить ее через конфигурацию. И вот, клиенты работают в Linux, не замечая никакой разницы, возможно, даже без необходимости перекомпиляции клиентского кода (по крайней мере, теоретически, а в некоторых языках - я знаю, что реальность в отношении многоплатформенных графических интерфейсов отличается, но это только пример: -)
Сравните это с попыткой реализовать то же самое без фабрик: у вас будет много мест в клиентском коде, где вам нужно будет решить, какой виджет для конкретной платформы вам нужно создать. И всякий раз, когда вы хотите представить новое семейство виджетов, вам нужно будет изменить каждое из этих мест в вашем коде, чтобы добавить новую ветвь для множества идентичных блоков switch
или if/else
. Более того, поскольку вы будете открыто иметь дело с объектами виджетов, зависящими от платформы, есть вероятность, что некоторые специфичные для платформы особенности виджетов и детали реализации попадут в клиентский код, что сделает его еще более трудным для переноса на другие платформы.
Реализация продукта никогда не изменяется независимо от каких-либо изменений, внесенных в класс продукта, вам все равно нужно внести изменения в класс клиента, чтобы передать новые значения Zin, необходимые для создания вашего обновленного продукта. Эти данные ведь должны откуда-то приходить?
Действительно. Если общий процесс создания экземпляра изменится, интерфейс Factory может измениться соответственно. Это не точка Фабрики. Хотя вы можете передавать данные на завод во время его создания, которые затем можно использовать в фоновом режиме при создании нового продукта.