Примечания к изучению шаблонов проектирования (3) Разница между простой фабрикой, фабричным методом и абстрактной фабрикой
Примечания к изучению шаблонов проектирования (3) Разница между простой фабрикой, фабричным методом и абстрактной фабрикой

Шаблон проектирования «Фабрика» в шаблонах проектирования — это широко используемый шаблон творческого проектирования, который можно разделить на три типа: «Простая фабрика», «Фабричный метод» и «Абстрактная фабрика». Так в чем же разница между этими тремя? Сначала поговорим о выводах:

  • простая фабрика:только один завод(простая фабрика), продуктинтерфейс/абстрактный класс, согласно простому фабрикавстатический метод для создания конкретного объекта-продукта. Подходит для сценариев, где мало продуктов и практически нет расширений.
  • фабричный метод:Есть несколько заводов(абстрактная фабрика+несколько конкретных заводов),продуктинтерфейс/абстрактный класс,Создайте конкретный продуктобъект полиморфно на основе методов, унаследованных от абстрактной фабрики. Применяется к нескольким продуктам одного типа
  • абстрактный метод:Есть несколько заводов(абстрактная фабрика+несколько конкретных заводов),Несколько продуктовинтерфейсов/абстрактных классов,Группировка подклассов продуктов,Полиморфно создавайте разные конкретные продуктобъекты одной группы на основе методов унаследованной абстрактной фабрики. Подходит для нескольких продуктов разных типов

Подробное объяснение ниже

1. Простой фабричный шаблон

1.1 Введение в простой фабричный шаблон

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

  • Productинтерфейс:Определите, что создаватьпродуктобъектизинтерфейс
  • ProductAProductBProductCпродуктдобрый:выполнитьпродуктинтерфейс,Особые характеристики интерфейса продукта
  • SimpleFactoryпростая фабрика:только один завод,проходитьстатический методcreateProductсоздаватьспецифическийизпродуктобъект
  • clientклиент:клиент Есть несколько,каждыйклиент Можетпроходитьпростая фабрика для создания конкретного объекта-продукта

1.2 Реализация простого фабричного шаблона

Давайте возьмем приведенную выше диаграмму классов в качестве примера для реализации простого шаблона фабрики:

Язык кода:javascript
копировать
/**продуктинтерфейс**/
public interface Product {

    void doSomething();
}

/**Конкретная реализация продукта**/
class ProductA implements Product{

    @Override
    public void doSomething() {
        System.out.println("Я ProductA");
    }
}

class ProductB implements Product{

    @Override
    public void doSomething() {
        System.out.println("Я ProductB");
    }
}

class ProductC implements Product{

    @Override
    public void doSomething() {
        System.out.println("Я ProductC");
    }
}
/**простая фабрика**/
public class SimpleFactory {
    /**Создание фабричного класса продуктстатический метод**/
    public static Product createProduct(String productName) {
        Product instance = null;
        switch (productName){
            case "A":
                instance = new ProductA();
                break;
            case "B":
                instance = new ProductB();
                break;
            case "C":
                instance = new ProductC();
        }
        return instance;
    }
    /**Клиент вызывает фабричный класс**/
    public static void main(String[] args) {
        SimpleFactory simpleFactory = new SimpleFactory();
        createProduct("A").doSomething();
        createProduct("B").doSomething();
    }
}
  • преимущество:простая фабрика может освободить клиента от ответственности за непосредственное создание объекта и создать соответствующий продукт по мере необходимости. Реализуйте разделение кодов классов клиента и продукта. Кроме того, через файл конфигурации можно добавлять новые конкретные классы продуктов без изменения клиентского кода (улучшение).
  • недостаток:Нарушать принцип открытия-закрытия,Если вам нужно добавить другие категории товаров,это должносуществоватьфабрикадобрыйсередина Новыйif-elseлогическое суждение(Можетпроходитьфайлы конфигурации для улучшения)。Но в целом,Расширение системы по-прежнему сложнее, чем у других заводских моделей.。 Мы обнаружили, что это просто Фабричный класс в шаблоне фабрика использует статический метод, так зачем это делать? Могу ли я использовать нестатические методы?
  • использоватьстатический метод Нет необходимости использоватьnewиз Способсоздаватьобъект,Удобно звонить
  • статический метод означает, что экземпляр может быть получен непосредственно объектом, нестатический метод можно вызвать только через конструктор (обычно частный) и к нему нельзя получить доступ за пределами фабричного класса.
  • Для некоторых сцен, где создание экземпляров и разрушение более чувствительны, например, «Пул». соединений с базой данных, экземпляр объекта может использоваться повторно и стабильно

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

1.3 Простые сценарии использования заводского режима

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

1.3.1 JDK, Spring и другие исходные коды

Есть такой дизайн на Яве,напримерDateFormatвэтотметодто естьпростая Применение фабрики

Язык кода:javascript
копировать
private static DateFormat get(LocaleProviderAdapter adapter, int timeStyle, int dateStyle, Locale loc) {
    DateFormatProvider provider = adapter.getDateFormatProvider();
    DateFormat dateFormat;
    //Логическое решение для достижения этого конкретного объекта
    if (timeStyle == -1) {
        dateFormat = provider.getDateInstance(dateStyle, loc);
    } else {
        if (dateStyle == -1) {
            dateFormat = provider.getTimeInstance(timeStyle, loc);
        } else {
            dateFormat = provider.getDateTimeInstance(dateStyle, timeStyle, loc);
        }
    }
    return dateFormat;
}

Кроме того, естьCalenderждать,существоватьSpring В исходном коде вы также можете увидеть некоторые классы, оканчивающиеся на «Factory», и все они используют шаблон «фабрика».

1.3.2 Пул соединений с базой данных

Например, когда бизнес подключается к базе данных,Необходимость поддержки различных баз данных,напримериметьdbcpc3p0druidждатьждать,В настоящее время методы подключения к базе данных ограничены.,И это относительно фиксировано, и его нелегко изменить.,так Вы можете попробовать использовать простой режим фабрики Для управления подключениями к базе данныхобъект。

2. Шаблон фабричного метода

Мы знаем, что простой шаблон фабрики имеет тот недостаток, что нарушает принцип открытия и закрытия, и его нелегко расширить. Поэтому среди 23 шаблонов проектирования GOF нет простого шаблона фабрики. Давайте посмотрим на другой шаблон фабрики: шаблон фабрики. Шаблон фабричного метода.

2.1 Введение в шаблон фабричного метода

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

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

  • Productинтерфейс:ипростая фабрикатакой же,поставлятьпродуктобъектизинтерфейс
  • ProductAProductBиproductC:специфическийдобрыйформаизпродуктобъект
  • FactoryAFactoryBиFactoryC:специфическийизпродуктфабрика,Реализовать конкретный продуктобъект
  • AbstractFactory:абстрактная фабрика,Может быть несколько,Метод отвечает за возврат созданного объекта-продукта.
  • Client:использовать该модельизклиент

2.2 Реализация шаблона фабричного метода

Согласно приведенной выше диаграмме классов мы можем реализовать соответствующий код:

Язык кода:javascript
копировать
/**продуктинтерфейс**/
public interface Product {

    void doSomething();
}

/**Конкретная реализация продукта**/
class ProductA implements Product{

    @Override
    public void doSomething() {
        System.out.println("Я ProductA");
    }
}

class ProductB implements Product{

    @Override
    public void doSomething() {
        System.out.println("Я ProductB");
    }
}

class ProductC implements Product{

    @Override
    public void doSomething() {
        System.out.println("Я ProductC");
    }
}

/**Заводской интерфейс**/
общественный interface AbstractFactory {
	/** Создаем метод Product, который отличается от статического заводского режима. метод**/
    public Product createProduct();
}

/**Конкретная фабричная реализация**/
class FactoryA implements AbstractFactory{

    @Override
    public Product createProduct() {
        return new ProductA();
    }
}

class FactoryA implements AbstractFactory{

    @Override
    public Product createProduct() {
        return new ProductA();
    }
}

class FactoryA implements AbstractFactory{

    @Override
    public Product createProduct() {
        return new ProductA();
    }
}
/**Клиент звонит на завод**/
public class Client {
    public static void main(String[] args) {
        Product productA = new FactoryA().createProduct();
        productA.doSomething();
        Product productB = new FactoryB().createProduct();
        productB.doSomething();
    }
}

Самым важным из которых является AbstractFactoryдобрыйвcreateProductметод,Используйте этот метод для создания конкретного продукта,Вот почему это называетсяфабричный метод причина. и простой фабрикаизстатический В отличие от метода, здесь используется нестатический метод вызова. И оказывается, что нет более простого фабрикав if-elseлогическое суждение,Условно говоря, масштабируемость намного сильнее.

  • преимущество:полностьювыполнитьпринцип открытия-закрытия,Реализованы расширяемые и более сложные иерархии. Уточнены обязанности,полиморфный,Применяется к любому классу сущностей.
  • недостаток:Если бизнес увеличивается,Это позволит удвоить количество классов в системе.,Повышенная сложность кода

2.3 Сценарии использования шаблона фабричного метода

2.3.1 Slf4j

В Slf4j Среди фреймворков, которые мы часто используем, есть фабричный методмодельизприложение,напримериспользовать频率很高изполучатьloggerобъект В примере:

private Logger logger = LoggerFactory.getLogger(Client.class);

Нажав на исходный код, чтобы увидеть, мы найдем этоgetLoggerметод:

Язык кода:javascript
копировать
//простая режим фабрики
public static Logger getLogger(String name) {
    /**фабричный Использование режима метода**/
    ILoggerFactory iLoggerFactory = getILoggerFactory();
    return iLoggerFactory.getLogger(имя);
}
//Заводской интерфейс
общественный interface ILoggerFactory {
    Logger getLogger(String var1);
}
//Loggerпродуктинтерфейс
public interface Logger {
    String ROOT_LOGGER_NAME = "ROOT";
    ...
}

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

2.3.2 Некоторый анализ конфигурации правил

Мы также можем использовать шаблон фабричного метода, когда требуются различные типы анализа конфигурации правил, например, цитируя код из «Красота шаблонов проектирования»:

Язык кода:javascript
копировать
public class RuleConfigSource {
  public RuleConfig load(String ruleConfigFilePath) {
    String ruleConfigFileExtension = getFileExtension(ruleConfigFilePath);

    IRuleConfigParserFactory parserFactory = RuleConfigParserFactoryMap.getParserFactory(ruleConfigFileExtension);
    if (parserFactory == null) {
      throw new InvalidRuleConfigException("Rule config file format is not supported: " + ruleConfigFilePath);
    }
    IRuleConfigParser parser = parserFactory.createParser();

    String configText = "";
    //Читаем текст конфигурации из файла ruleConfigFilePath в configText
    RuleConfig ruleConfig = parser.parse(configText);
    return ruleConfig;
  }

  private String getFileExtension(String filePath) {
    //...Разбираем имя файла, чтобы получить расширение, например, rule.json, и возвращаем json
    return "json";
  }
}

//Поскольку фабричный класс содержит только методы и не содержит переменных-членов, его можно полностью использовать повторно.
//Нет необходимости каждый раз создавать новый фабричный класс, поэтому все просто режим фабрикииз Второй видвыполнить Идея более правильная。
public class RuleConfigParserFactoryMap { //Завод фабрики
  private static final Map<String, IRuleConfigParserFactory> cachedFactories = new HashMap<>();

  static {
    cachedFactories.put("json", new JsonRuleConfigParserFactory());
    cachedFactories.put("xml", new XmlRuleConfigParserFactory());
    cachedFactories.put("yaml", new YamlRuleConfigParserFactory());
    cachedFactories.put("properties", new PropertiesRuleConfigParserFactory());
  }

  public static IRuleConfigParserFactory getParserFactory(String type) {
    if (type == null || type.isEmpty()) {
      return null;
    }
    IRuleConfigParserFactory parserFactory = cachedFactories.get(type.toLowerCase());
    return parserFactory;
  }
}

Если вам нужно добавить новый анализатор конфигурации правил, вам нужно всего лишь создать новый parser класс и parserfactory Выполняйте различные конфигурации

3. Абстрактная фабрика

Абстрактный фабричный узор Нет простого фабрикаифабричный Режим метода очень часто используется, но сцена совершенно особенная. фабрикаифабричный В методе существует только один метод классификации классов, например простой фабрикасередина,в соответствии спродуктдобрыйформа分为ProductAProductBиProductC。但是如果иметь多种分добрый Способ,Например, согласно классификации производителя продукта,ProductAвозможныйиProductCза одногодобрый。Это используетсяабстрактная фабрикамодель

3.1 Введение в шаблон абстрактной фабрики

Абстрактная фабрика (абстрактная Factory Pattern) — творческий узор, который на самом деле является отражением фабричного Расширение шаблона метода эквивалентно суперфабрике, используемой для создания других шаблонов фабрики. В шаблоне абстрактной фабрики интерфейс отвечает за создание фабрики, связанной с объектом, и каждая фабрика может предоставлять объект в соответствии с шаблоном фабрики. Фактически, абстрактная фабрика призвана еще и сократить фабричный методвребеноккласс Количество фабричного класса, на основе предложенного шаблона Проект, как показано ниже (источник: Taoxi Technology):

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

  • Product1иProduct2:определитьдобрыйформаизпродуктобъектинтерфейс
  • Product1AProduct1Bждать:Различныйдобрыйформаизспецифическийпродуктобъект
  • FactoryAиFactoryB:специфическийпродуктфабрика,Отвечает за создание объект-продукта этого типа фабрики.
  • AbstractFactory:абстрактная фабрикаинтерфейс,Определить класс объекта-продукта
  • Client:клиент,Используйте абстрактную фабрику,вызовпродуктобъект

3.2 Реализация шаблона абстрактной фабрики

Далее, на основе приведенной выше диаграммы классов, используйте код для реализации абстрактной фабрики:

Язык кода:javascript
копировать
/**Product1добрыйизпродуктинтерфейс**/
public interface Product1 {
    void doSomething();
}

class Product1A implements Product1{

    @Override
    public void doSomething() {
        System.out.println("Я Product1A");
    }
}

class Product1B implements Product1{

    @Override
    public void doSomething() {
        System.out.println("Я Product1B");
    }
}


/** Product2добрыйизпродуктинтерфейс**/
public interface Product2 {
    void doSomething();
}

class Product2A implements Product1{

    @Override
    public void doSomething() {
        System.out.println("Я Product2A");
    }
}

class Product2B implements Product1{

    @Override
    public void doSomething() {
        System.out.println("Я Product2B");
    }
}

/**Абстрактный заводской интерфейс**/
public interface AbstractFactory {

    public Product1 createProduct1();

    public Product2 createProduct2();
}

/**Завод класса А**/
public class FactoryA implements AbstractFactory{

    @Override
    public Product1 createProduct1() {
        return new Product1A();
    }

    @Override
    public Product2 createProduct2() {
        return new Product2A();
    }
}

/**Завод класса B**/
public class FactoryB implements AbstractFactory{

    @Override
    public Product1 createProduct1() {
        return new Product1B();
    }

    @Override
    public Product2 createProduct2() {
        return new Product2B();
    }
}


/**Вызов клиента-клиента**/
public class Client {
    public static void main(String[] args) {
        new FactoryA().createProduct1().doSomething();
        new FactoryB().createProduct2().doSomething();
    }
}
  • преимущество:Добавлять группы стало проще,И это может значительно сократить количество фабричных классов.
  • недостаток:из-за группировки,так Группавпродукт Расширение сложнее,Например, добавьте еще один Product3,Это нужно изменитьAbstractFactoryFactoryAиFactoryB几乎所иметьфабрикадобрый

Подводя итог, ни один метод не является панацеей. Какую модель фабрики следует использовать в соответствии с бизнес-сценарием?

Ссылки

https://www.zhihu.com/question/27125796/answer/1615074467

«Повторное изучение шаблонов проектирования»

https://www.cnblogs.com/sunweiye/p/10815928.html

https://time.geekbang.org/column/article/197254

boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose