简介
- 简单工厂:适合单一产品、创建逻辑简单的场景,但不符合开闭原则。
- 工厂方法:适合需要扩展多种具体产品的场景,符合开闭原则。
- 抽象工厂:适合需要创建一组相关对象的场景,支持切换整个产品簇。
简单工厂模式
通过一个工厂类集中处理对象的创建逻辑,根据传入的参数决定创建哪一种产品类的实例。
java
// 抽象产品
interface Product {
void use();
}
// 具体产品A
class ConcreteProductA implements Product {
public void use() {
System.out.println("Using Product A");
}
}
// 具体产品B
class ConcreteProductB implements Product {
public void use() {
System.out.println("Using Product B");
}
}
// 简单工厂
class SimpleFactory {
public Product createProduct(String type) {
switch (type) {
case "A":
return new ConcreteProductA();
case "B":
return new ConcreteProductB();
default:
throw new IllegalArgumentException("Unknown product type");
}
}
}
// 客户端调用
public class Client {
public static void main(String[] args) {
SimpleFactory factory = new SimpleFactory();
Product product = factory.createProduct("A");
product.use(); // 输出: Using Product A
}
}
工厂方法模式
定义了一个用于创建对象的接口,但让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
核心结构:
- Product(抽象产品):定义产品的公共接口。
- ConcreteProduct(具体产品):实现 Product 接口的具体类。
- Factory(抽象工厂):声明一个工厂方法,用于创建 Product 对象。
- ConcreteFactory(具体工厂):实现工厂方法,返回一个具体的 ConcreteProduct 实例。
java
// 抽象产品
interface Product {
void use();
}
// 具体产品A
class ConcreteProductA implements Product {
public void use() {
System.out.println("Using Product A");
}
}
// 具体产品B
class ConcreteProductB implements Product {
public void use() {
System.out.println("Using Product B");
}
}
// 抽象工厂
abstract class Factory {
// 工厂方法
abstract Product createProduct();
// 使用产品的方法
void doSomething() {
Product product = createProduct();
product.use();
}
}
// 具体工厂A
class FactoryA extends Factory {
@Override
Product createProduct() {
return new ConcreteProductA();
}
}
// 具体工厂B
class FactoryB extends Factory {
@Override
Product createProduct() {
return new ConcreteProductB();
}
}
// 客户端调用
public class Client {
public static void main(String[] args) {
Factory factoryA = new FactoryA();
factoryA.doSomething(); // 输出: Using Product A
Factory factoryB = new FactoryB();
factoryB.doSomething(); // 输出: Using Product B
}
}
抽象工厂模式
提供一个接口,用于创建一组相关或依赖对象的家族,而无需指定具体类。 这在需要为不同的"产品族"提供统一的创建方式时非常有用,比如: 不同操作系统下的 UI 控件(按钮、文本框等); 不同风格的主题(深色、浅色); 多平台客户端(PC、移动端)所需的一整套组件。
接口和抽象类都可以实现抽象工厂模式, 但更倾向于使用 接口(interface) 来实现抽象工厂,因为: 更符合面向接口编程的思想; 支持多继承; 可以配合默认方法提供更灵活的设计。
下面是一个完整的 抽象工厂模式(Abstract Factory Pattern) 的 Java 示例实现,涵盖了:
- 抽象工厂接口
- 具体工厂类
- 抽象产品接口
- 具体产品类
- 客户端调用
这个例子以"不同风格的 UI 控件"为例:比如 Windows 风格和 Mac 风格的按钮和文本框。
1. 定义抽象产品接口
Button.java
- 按钮接口
java
public interface Button {
void render();
}
TextBox.java
- 文本框接口
java
public interface TextBox {
void render();
}
2. 实现具体产品类
WindowsButton.java
java
class WindowsButton implements Button {
public void render() {
System.out.println("Render a Windows style button.");
}
}
MacButton.java
java
class MacButton implements Button {
public void render() {
System.out.println("Render a Mac style button.");
}
}
WindowsTextBox.java
java
class WindowsTextBox implements TextBox {
public void render() {
System.out.println("Render a Windows style text box.");
}
}
MacTextBox.java
java
class MacTextBox implements TextBox {
public void render() {
System.out.println("Render a Mac style text box.");
}
}
3. 定义抽象工厂接口
UIFactory.java
java
public interface UIFactory {
Button createButton(); // 创建按钮
TextBox createTextBox(); // 创建文本框
}
4. 实现具体工厂类
WindowsFactory.java
java
class WindowsFactory implements UIFactory {
public Button createButton() {
return new WindowsButton();
}
public TextBox createTextBox() {
return new WindowsTextBox();
}
}
MacFactory.java
java
class MacFactory implements UIFactory {
public Button createButton() {
return new MacButton();
}
public TextBox createTextBox() {
return new MacTextBox();
}
}
5. 编写客户端代码使用抽象工厂
Client.java
java
public class Client {
private Button button;
private TextBox textBox;
public Client(UIFactory factory) {
this.button = factory.createButton();
this.textBox = factory.createTextBox();
}
public void renderUI() {
button.render();
textBox.render();
}
public static void main(String[] args) {
String osType = "mac"; // 可改为 "windows"
UIFactory factory;
if ("windows".equalsIgnoreCase(osType)) {
factory = new WindowsFactory();
} else {
factory = new MacFactory();
}
Client client = new Client(factory);
client.renderUI();
}
}
输出结果(当 osType = "mac")
css
Render a Mac style button.
Render a Mac style text box.
总结
角色 | 类名 |
---|---|
抽象产品A | Button |
抽象产品B | TextBox |
具体产品A1 | WindowsButton |
具体产品A2 | MacButton |
具体产品B1 | WindowsTextBox |
具体产品B2 | MacTextBox |
抽象工厂 | UIFactory |
具体工厂1 | WindowsFactory |
具体工厂2 | MacFactory |
扩展建议
- 如果需要新增一个控件类型(如
ComboBox
),只需在抽象工厂中添加新方法,并在所有具体工厂中实现。 - 若使用 Java 8+,可在接口中提供默认实现,提高灵活性。
- 结合 Spring 或其他 IOC 框架可以实现更优雅的解耦与配置切换。