diff --git a/localization/ru/abstract-factory/README.md b/localization/ru/abstract-factory/README.md new file mode 100644 index 000000000000..044e03c53c5c --- /dev/null +++ b/localization/ru/abstract-factory/README.md @@ -0,0 +1,237 @@ +--- +title: Abstract Factory +category: Creational +language: ru +tag: + - Gang of Four +--- + +## Альтернативные названия +Kit + +## Цель +Предоставление интерфейса для создания семейств взаимосвязанных или взаимозависимых объектов без указания их конкретных классов. + +## Объяснение +Пример из реального мира: +> Представьте, что вы хотите создать королевство с замком, королём и армией. Эльфийскому королевству понадобится эльфийский замок, эльфийский король и эльфийская армия, в то время как оркскому королевству понадобится оркский замок, оркский король и оркская армия. Между объектами королевства существует взаимозависимость. + +Простыми словами: +> Фабрика фабрик; фабрика, которая объединяет отдельные, но взаимозависимые/взаимозаменяемые фабрики без указания их конкретных классов. + +Википедия пишет: +> Порождающий шаблон проектирования, предоставляет интерфейс для создания семейств взаимосвязанных или взаимозависимых объектов, не специфицируя их конкретных классов. + +**Программный пример**\ +Основываясь на примере королевства выше, во-первых, нам понадобятся интерфейсы и реализации для объектов в королевстве. + +```java +public interface Castle { + String getDescription(); +} + +public interface King { + String getDescription(); +} + +public interface Army { + String getDescription(); +} + +// Эльфийская реализация +public class ElfCastle implements Castle { + static final String DESCRIPTION = "Это эльфийский замок!"; + @Override + public String getDescription() { + return DESCRIPTION; + } +} +public class ElfKing implements King { + static final String DESCRIPTION = "Это эльфийский король!"; + @Override + public String getDescription() { + return DESCRIPTION; + } +} +public class ElfArmy implements Army { + static final String DESCRIPTION = "Это эльфийская армия!"; + @Override + public String getDescription() { + return DESCRIPTION; + } +} + +// Оркская реализация +public class OrcCastle implements Castle { + static final String DESCRIPTION = "Это оркский замок!"; + @Override + public String getDescription() { + return DESCRIPTION; + } +} +public class OrcKing implements King { + static final String DESCRIPTION = "Это оркский король!"; + @Override + public String getDescription() { + return DESCRIPTION; + } +} +public class OrcArmy implements Army { + static final String DESCRIPTION = "Это оркская армия!"; + @Override + public String getDescription() { + return DESCRIPTION; + } +} +``` + +Во-вторых, нам понадобятся абстракция фабрики королевства, а также реализации этой абстракции: + +```java +public interface KingdomFactory { + Castle createCastle(); + King createKing(); + Army createArmy(); +} + +public class ElfKingdomFactory implements KingdomFactory { + + @Override + public Castle createCastle() { + return new ElfCastle(); + } + + @Override + public King createKing() { + return new ElfKing(); + } + + @Override + public Army createArmy() { + return new ElfArmy(); + } +} + +public class OrcKingdomFactory implements KingdomFactory { + + @Override + public Castle createCastle() { + return new OrcCastle(); + } + + @Override + public King createKing() { + return new OrcKing(); + } + + @Override + public Army createArmy() { + return new OrcArmy(); + } +} +``` + +На данный момент, у нас есть абстрактная фабрика, которая позволяет создавать семейство взаимосвязанных объектов, то есть фабрика эльфийского королевства создаёт эльфийский замок, эльфийского короля, эльфийскую армию и так далее: + +```java +var factory = new ElfKingdomFactory(); +var castle = factory.createCastle(); +var king = factory.createKing(); +var army = factory.createArmy(); + +castle.getDescription(); +king.getDescription(); +army.getDescription(); +``` + +Вывод программы: + +``` +Это эльфийский замок! +Это эльфийский король! +Это эльфийская армия! +``` + +Можно спроектировать фабрику для наших различных фабрик королевств. В следующем примере, мы создали `FactoryMaker`, который ответственен за создание экземпляра `ElfKingdomFactory`, либо `OrcKingdomFactory`. + +Клиент может использовать класс `FactoryMaker`, чтобы создать желаемую конкретную фабрику, которая в свою очередь будет производить разные конкретные объекты, унаследованные от `Castle`, `King`, `Army`. + +В этом примере использовано перечисление, чтобы параметризовать то, какую фабрику королевства запрашивает клиент: + +```java +public static class FactoryMaker { + public enum KingdomType { + ELF, ORC + } + + public static KingdomFactory makeFactory(KingdomType type) { + return switch (type) { + case ELF -> new ElfKingdomFactory(); + case ORC -> new OrcKingdomFactory(); + default -> throe new IllegalArgumentException("Данный тип королества не поддерживается.") + } + } +} + + public static void main(String[] args) { + var app = new App(); + + LOGGER.info("Эльфийское королевство"); + app.createKingdom(FactoryMaker.makeFactory(KingdomType.ELF)); + LOGGER.indo(app.getCastle().getDescription()); + LOGGER.indo(app.getKinv().getDescription()); + LOGGER.indo(app.getArmy().getDescription()); + + LOGGER.info("Оркское королевство"); + + app.createKingdom(FactoryMaker.makeFactory(KingdomType.ORC)); + LOGGER.indo(app.getCastle().getDescription()); + LOGGER.indo(app.getKinv().getDescription()); + LOGGER.indo(app.getArmy().getDescription()); + } + +``` + +## Диаграмма классов +![Диаграмма классов паттерна проектирования абстрактная фабрика](../../../abstract-factory/etc/abstract-factory.urm.png) + +## Применимость +Используйте шаблон проектирования абстрактная фабрика, когда: + +- Система должна быть независимой от того, как создаются, составляются и представляются её продукты; +- Система должна быть сконфигурирована одним из нескольких семейств продуктов; +- Семейство связанных продуктов спроектировано для совместного использования и вам необходимо обеспечить соблюдение данного ограничения; +- Вы хотите предоставить библиотеку классов, но готовы раскрыть только их интерфейсы, но не реализацию; +- Время жизни зависимости концептуально короче, чем время жизни потребителя; +- Вам требуется значение времени исполнения, чтобы создать требуемую зависимость; +- Вы хотите решить какие продукты из семейства вам нужны во время исполнения; +- Вам нужно предоставить один или несколько параметров, которые известны только во время исполнения прежде, чем вы сможете решить зависимость; +- В случае, когда требуется последовательность среди продуктов; +- Вы не хотите менять существующий код, когда добавляются новые продукты или семейство продуктов в программе. + +Примеры сценариев использования: + +- Выбор необходимой реализации FileSystemAcmeService или DataBaseAcmeSerivce или NetworkAcmeService во времени выполнения; +- Написание модульных тестов становится намного легче; +- Элементы графического пользовательского интерфейса для различных операционных систем. + +## Следствия +- Внедрение зависимости в Java скрывает зависимости класса, приводящие к ошибкам времени выполнения, которые могли-бы быть обнаружены во времени компиляции; +- Данный паттерн проектирования отлично справляется с задачей создания уже определённых объектов, но добавление новых может быть трудоёмким; +- Код становится сложнее, чем ему следует из-за появления большого количества новых интерфейсов и классов, которые появляются вместе с этим паттерном проектирования. + +## Руководства +* [Abstract Factory Pattern Tutorial](https://www.journaldev.com/1418/abstract-factory-design-pattern-in-java) + +## Известные применения +* [javax.xml.parsers.DocumentBuilderFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/parsers/DocumentBuilderFactory.html) +* [javax.xml.transform.TransformerFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/transform/TransformerFactory.html#newInstance--) +* [javax.xml.xpath.XPathFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/xpath/XPathFactory.html#newInstance--) + +## Родственные паттерны проектирования +* [Factory Method](https://java-design-patterns.com/patterns/factory-method/) +* [Factory Kit](https://java-design-patterns.com/patterns/factory-kit/) + +## Благодарности +* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59) +* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)