Примечания к изучению шаблонов проектирования (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
Облачный шлюз Spring реализует примеры балансировки нагрузки и проверки входа в систему.
boy illustration
Используйте Nginx для решения междоменных проблем
boy illustration
Произошла ошибка, когда сервер веб-сайта установил соединение с базой данных. WordPress предложил решение проблемы с установкой соединения с базой данных... [Легко понять]
boy illustration
Новый адрес java-библиотеки_16 топовых Java-проектов с открытым исходным кодом, достойных вашего внимания! Обязательно к просмотру новичкам
boy illustration
Лучшие практики Kubernetes для устранения несоответствий часовых поясов внутри контейнеров
boy illustration
Введение в проект удаления водяных знаков из коротких видео на GitHub Douyin_TikTok_Download_API
boy illustration
Весенние аннотации: подробное объяснение @Service!
boy illustration
Пожалуйста, не используйте foreach для пакетной вставки в MyBatis. Для 5000 фрагментов данных потребовалось 14 минут. .
boy illustration
Как создать проект Node.js с помощью npm?
boy illustration
Mybatis-plus использует typeHandler для преобразования объединенных строк String в списки списков.
boy illustration
Не удалось установить программное обеспечение Mitsubishi. Возможно, возникла проблема с реестром.
boy illustration
Разрешение ошибок проекта SpringBoot 3 mybatis-plus: org.apache.ibatis.binding.BindingException: неверный оператор привязки
boy illustration
Более краткая проверка параметров. Для проверки параметров используйте SpringBoot Validation.
boy illustration
Поиграйтесь с интеграцией Spring Boot (платформа запланированных задач Quartz)
boy illustration
Несколько популярных режимов интерфейса API: RESTful, GraphQL, gRPC, WebSocket, Webhook.
boy illustration
Redis: практика публикации (pub) и подписки (sub)
boy illustration
Подробное объяснение пакета Golang Context
boy illustration
Краткое руководство: создайте свое первое приложение .NET Aspire
boy illustration
Краткое обсуждение метода пакетной вставки MyBatis: обработка 100 000 фрагментов данных занимает всего 2 секунды.
boy illustration
[Инструмент] Используйте nvm для управления переключением версий nodejs, это так здорово!
boy illustration
HTML можно преобразовать в word_html для отображения текстовых документов.
boy illustration
Статья Spring Security 6.x для быстрого понимания принципов настройки
boy illustration
Не забудьте изменить имя каждого модуля RUOYI один раз, чтобы избежать мошенничества ~~~
boy illustration
Научите вас шаг за шагом, как интегрировать систему обслуживания клиентов Hunyuan AI Q&A от 0 до 1.
boy illustration
Подробное объяснение Gzip: принципы и применение алгоритмов сжатия.
boy illustration
Скачать Tomcat - ссылка для скачивания на официальном сайте tomcat7, tomcat8, tomcat9
boy illustration
Развертывание IIS.NetCore
boy illustration
[Оптимизация памяти Android] Общие функции инструмента Android Profiler (мониторинг памяти | снимок памяти)
boy illustration
Встроенная в Springboot пользовательская конфигурация временного каталога, связанного с Tomcat.
boy illustration
Краткое руководство по началу работы с Element-UI