Шаблон проектирования «Фабрика» в шаблонах проектирования — это широко используемый шаблон творческого проектирования, который можно разделить на три типа: «Простая фабрика», «Фабричный метод» и «Абстрактная фабрика». Так в чем же разница между этими тремя? Сначала поговорим о выводах:
Подробное объяснение ниже
Простой шаблон фабрики также называется шаблоном статического фабричного метода, который использует статические методы для получения различных параметров и возврата различных объектов экземпляра. Поясним с помощью диаграммы классов:
Product
интерфейс:Определите, что создаватьпродуктобъектизинтерфейсProductA
、ProductB
、ProductC
продуктдобрый:выполнитьпродуктинтерфейс,Особые характеристики интерфейса продуктаSimpleFactory
простая фабрика:только один завод,проходитьстатический методcreateProduct
создаватьспецифическийизпродуктобъектclient
клиент:клиент Есть несколько,каждыйклиент Можетпроходитьпростая фабрика для создания конкретного объекта-продуктаДавайте возьмем приведенную выше диаграмму классов в качестве примера для реализации простого шаблона фабрики:
/**продуктинтерфейс**/
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
из Способсоздаватьобъект,Удобно звонитьПодводя итог, можно сказать, что модель простой фабрики подходит для ситуаций, когда бизнес прост, продукты фиксированы, а класс фабрики не будет часто меняться.
Давайте посмотрим, для каких бизнес-сценариев обычно используется простой фабричный шаблон.
Есть такой дизайн на Яве,напримерDateFormat
вэтотметодто естьпростая Применение фабрики
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», и все они используют шаблон «фабрика».
Например, когда бизнес подключается к базе данных,Необходимость поддержки различных баз данных,напримериметьdbcp
、c3p0
、druid
ждатьждать,В настоящее время методы подключения к базе данных ограничены.,И это относительно фиксировано, и его нелегко изменить.,так Вы можете попробовать использовать простой режим фабрики Для управления подключениями к базе данныхобъект。
Мы знаем, что простой шаблон фабрики имеет тот недостаток, что нарушает принцип открытия и закрытия, и его нелегко расширить. Поэтому среди 23 шаблонов проектирования GOF нет простого шаблона фабрики. Давайте посмотрим на другой шаблон фабрики: шаблон фабрики. Шаблон фабричного метода.
Проблема, которую хочет решить шаблон абстрактной фабрики, — это проблема выбора интерфейса, когда в семействе продуктов имеется несколько разных типов продуктов.
Шаблон фабричного метода на самом деле является модернизацией простого шаблона фабрики. В дополнение к интерфейсу продукта шаблон фабричного метода также определяет интерфейс для создания фабрики объектов, позволяя подклассу фабрики создавать экземпляр соответствующего класса продукта. Объясняется через диаграмму классов:
Product
интерфейс:ипростая фабрикатакой же,поставлятьпродуктобъектизинтерфейсProductA
、ProductB
иproductC
:специфическийдобрыйформаизпродуктобъектFactoryA
、FactoryB
иFactoryC
:специфическийизпродуктфабрика,Реализовать конкретный продуктобъектAbstractFactory
:абстрактная фабрика,Может быть несколько,Метод отвечает за возврат созданного объекта-продукта.Client
:использовать该модельизклиентСогласно приведенной выше диаграмме классов мы можем реализовать соответствующий код:
/**продуктинтерфейс**/
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
логическое суждение,Условно говоря, масштабируемость намного сильнее.
В Slf4j Среди фреймворков, которые мы часто используем, есть фабричный методмодельизприложение,напримериспользовать频率很高изполучатьlogger
объект В примере:
private Logger logger = LoggerFactory.getLogger(Client.class);
Нажав на исходный код, чтобы увидеть, мы найдем этоgetLogger
метод:
//простая режим фабрики
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
Экземпляр объекта, это типичное применение шаблона фабричного метода.
Мы также можем использовать шаблон фабричного метода, когда требуются различные типы анализа конфигурации правил, например, цитируя код из «Красота шаблонов проектирования»:
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
Выполняйте различные конфигурации
Абстрактный фабричный узор Нет простого фабрикаифабричный Режим метода очень часто используется, но сцена совершенно особенная. фабрикаифабричный В методе существует только один метод классификации классов, например простой фабрикасередина,в соответствии спродуктдобрыйформа分为ProductA
、ProductB
иProductC
。但是如果иметь多种分добрый Способ,Например, согласно классификации производителя продукта,ProductA
возможныйиProductC
за одногодобрый。Это используетсяабстрактная фабрикамодель
Абстрактная фабрика (абстрактная Factory Pattern) — творческий узор, который на самом деле является отражением фабричного Расширение шаблона метода эквивалентно суперфабрике, используемой для создания других шаблонов фабрики. В шаблоне абстрактной фабрики интерфейс отвечает за создание фабрики, связанной с объектом, и каждая фабрика может предоставлять объект в соответствии с шаблоном фабрики. Фактически, абстрактная фабрика призвана еще и сократить фабричный методвребеноккласс Количество фабричного класса, на основе предложенного шаблона Проект, как показано ниже (источник: Taoxi Technology):
пример книги предложенийにдобавление В методе мы можем классифицировать их только по клавиатуре, хосту и монитору, что приведет к появлению большого количества фабрик класса. подкласс ипродукт. Абстрактная фабрика может группировать вышеуказанные три класса продуктов, что может значительно сократить количество фабричных классов. Давайте посмотрим на соответствующую диаграмму классов:
Product1
иProduct2
:определитьдобрыйформаизпродуктобъектинтерфейсProduct1A
、Product1B
ждать:РазличныйдобрыйформаизспецифическийпродуктобъектFactoryA
иFactoryB
:специфическийпродуктфабрика,Отвечает за создание объект-продукта этого типа фабрики.AbstractFactory
:абстрактная фабрикаинтерфейс,Определить класс объекта-продуктаClient
:клиент,Используйте абстрактную фабрику,вызовпродуктобъектДалее, на основе приведенной выше диаграммы классов, используйте код для реализации абстрактной фабрики:
/**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();
}
}
AbstractFactory
、FactoryA
иFactoryB
几乎所иметьфабрикадобрыйПодводя итог, ни один метод не является панацеей. Какую модель фабрики следует использовать в соответствии с бизнес-сценарием?
https://www.zhihu.com/question/27125796/answer/1615074467
«Повторное изучение шаблонов проектирования»