Mike Liu c5a4068e84
docs: Translation for zh (#1805)
* add state and callback pattern

* add command and template-method pattern

* add iterator pattern

* add bridege and DI pattern

* fix issue #1600

* add converter,proxy,visitor pattern

* add caching,composite,delegation,dirty-flag,interpreter patterns

* add dao and producer-consumer

* add dto and provate class data pattern

* fix #1646 png path problems

* fix #1646 composite png path case problem

* add abstract document pattern and version-number pattern

* add ambassador pattern

* add acyclic-visitor and api-gateway pattern

* add abstract-factory pattern

* add active-object pattern

* add aggregator-microservices and arrange-act-assert pattern

* update async-method-invocation pattern

* add balking and business-delegate pattern

* add bytecode and circuit-break pattern

* update arrange/act/assert pattern problems

* add csch pattern

* add language code, correct pic path

* #1805 update permalink

Co-authored-by: Subhrodip Mohanta <subhrodipmohanta@gmail.com>
Co-authored-by: Mike <admin@xiaod.info>
Co-authored-by: Ilkka Seppälä <iluwatar@users.noreply.github.com>
2021-08-01 20:25:54 +05:30

143 lines
4.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
layout: pattern
title: Factory
folder: factory
permalink: /patterns/factory/
categories: Creational
language: zh
tags:
- Gang of Four
---
## 也被称为
* 简单工厂
* 静态工厂方法
## 含义
在工厂类中提供一个封装的静态工厂方法,用于隐藏对象初始化细节,使客户端代码可以专注于使用,而不用关心类的初始化过程。
## 解释
现实例子
>
> 假设我们有一个需要连接到 SQL Server 的 Web 应用,但现在我们需要切换到连接 Oracle。为了不修改现有代码的情况下做到这一点我们需要实现简单工厂模式。在这种模式下可以通过调用一个静态方法来创建与给定数据库的连接。
维基百科
> 工厂类是一个用于创建其他对象的对象 -- 从形式上看,工厂方法是一个用于返回不同原型或类型的函数或方法。
**编程示例**
我们有一个 `Car` 接口,以及实现类 `Ford`, `Ferrari`
```java
public interface Car {
String getDescription();
}
public class Ford implements Car {
static final String DESCRIPTION = "This is Ford.";
@Override
public String getDescription() {
return DESCRIPTION;
}
}
public class Ferrari implements Car {
static final String DESCRIPTION = "This is Ferrari.";
@Override
public String getDescription() {
return DESCRIPTION;
}
}
```
Enumeration above represents types of cars that we support (`Ford` and `Ferrari`).
以下的枚举用于表示支持的 `Car` 类型(`Ford``Ferrari`
```java
public enum CarType {
FORD(Ford::new),
FERRARI(Ferrari::new);
private final Supplier<Car> constructor;
CarType(Supplier<Car> constructor) {
this.constructor = constructor;
}
public Supplier<Car> getConstructor() {
return this.constructor;
}
}
```
接着我们实现了一个静态方法 `getCar` 用于封装工厂类 `CarsFactory` 创建 `Car` 具体对象实例的细节。
```java
public class CarsFactory {
public static Car getCar(CarType type) {
return type.getConstructor().get();
}
}
```
现在我们可以在客户端代码中通过工厂类创建不同类型的 `Car` 对象实例。
```java
var car1 = CarsFactory.getCar(CarType.FORD);
var car2 = CarsFactory.getCar(CarType.FERRARI);
LOGGER.info(car1.getDescription());
LOGGER.info(car2.getDescription());
```
程序输出:
```java
This is Ford.
This is Ferrari.
```
## 类图
![alt text](../../../factory/etc/factory.urm.png "Factory pattern class diagram")
## 适用场景
在你只关心对象的创建,但不关心如何创建、管理它的时候,请使用简单工厂模式。
**优点**
* 可以把对象创建代码集中在一个地方,避免在代码库存散布 "new" 关键字。
* 可以让代码更加低耦合。它的一些主要优点包括更好的可测试性、更好的可读性、组件可替换性、可拓展性、更好的隔离性。
**缺点**
* 会使代码变得比原来的更加复杂一些。
## 现实案例
* [java.util.Calendar#getInstance()](https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html#getInstance--)
* [java.util.ResourceBundle#getBundle()](https://docs.oracle.com/javase/8/docs/api/java/util/ResourceBundle.html#getBundle-java.lang.String-)
* [java.text.NumberFormat#getInstance()](https://docs.oracle.com/javase/8/docs/api/java/text/NumberFormat.html#getInstance--)
* [java.nio.charset.Charset#forName()](https://docs.oracle.com/javase/8/docs/api/java/nio/charset/Charset.html#forName-java.lang.String-)
* [java.net.URLStreamHandlerFactory#createURLStreamHandler(String)](https://docs.oracle.com/javase/8/docs/api/java/net/URLStreamHandlerFactory.html) (Returns different singleton objects, depending on a protocol)
* [java.util.EnumSet#of()](https://docs.oracle.com/javase/8/docs/api/java/util/EnumSet.html#of(E))
* [javax.xml.bind.JAXBContext#createMarshaller()](https://docs.oracle.com/javase/8/docs/api/javax/xml/bind/JAXBContext.html#createMarshaller--) and other similar methods.
## 相关模式
* [Factory Method](https://java-design-patterns.com/patterns/factory-method/)
* [Factory Kit](https://java-design-patterns.com/patterns/factory-kit/)
* [Abstract Factory](https://java-design-patterns.com/patterns/abstract-factory/)