# 设计模式

#### 总结

枚举类型实现单例模式是非常推荐的做法，尤其是在 Java 5 及以后的版本。它简单、线程安全、避免了反射和序列化带来的问题，且保证了单例模式的正确性。对于绝大多数的单例模式实现需求，枚举类型是最安全、最简洁、最优雅的解决方案。

## 工厂模式

工厂模式（Factory Pattern）是创建型设计模式的一种，它提供了一种创建对象的方式，而不需要暴露具体的类实例化过程。

工厂模式适用于以下场景：

- **对象创建逻辑复杂**：当对象的创建过程比较复杂，包含多个初始化步骤时。
- **类的创建与实现解耦**：客户端只关心产品的接口，而不关心具体实现。
- **动态选择不同类型的对象**：需要根据不同条件动态选择创建的对象类型。
- **产品种类变化频繁**：产品的类型变化较多时，使用工厂模式能使扩展更加灵活。
- **避免客户端直接实例化**：通过工厂封装对象的创建过程，减少客户端与具体实现的耦合。

### 1. **简单工厂模式（Simple Factory Pattern）**

简单工厂模式是工厂模式的一种简单形式，**它并不属于设计模式中的结构**，它是通过一个工厂类来决定创建哪一个产品类的实例。

- 特点
    - 由工厂类来决定实例化哪个产品类，不暴露具体的产品创建过程。
    - 客户端不需要知道产品类的具体信息，减少了与产品类的耦合。
- 优缺点
    - 优点：客户端不需要关心对象的创建细节，降低了代码的耦合度。
    - 缺点：工厂类需要维护一个 `if` 或 `switch` 来判断创建哪种产品，如果产品种类增加，工厂类会变得非常庞大且难以维护。

**示例**：

```java
class Product {
    void use() {
        System.out.println("Using the product");
    }
}

class ConcreteProductA extends Product {
    @Override
    void use() {
        System.out.println("Using Product A");
    }
}

class ConcreteProductB extends Product {
    @Override
    void use() {
        System.out.println("Using Product B");
    }
}

class SimpleFactory {
    public Product createProduct(String type) {
        if (type.equals("A")) {
            return new ConcreteProductA();
        } else if (type.equals("B")) {
            return new ConcreteProductB();
        } else {
            return null;
        }
    }
}

public class Client {
    public static void main(String[] args) {
        SimpleFactory factory = new SimpleFactory();
        Product product = factory.createProduct("A");
        product.use();
    }
}
```

### 2. **工厂方法模式（Factory Method Pattern）**

工厂方法模式是工厂模式的核心。它通过定义一个接口来创建对象，由子类来决定实例化哪一个类。工厂方法模式将简单工厂中的创建产品的逻辑分散到了各个具体的工厂类中。

- 特点
    - 定义一个创建对象的接口，但让子类来决定具体实例化哪一个产品。
    - 通过继承和多态来解决简单工厂的缺点，避免了在一个类中维护大量的 `if` 或 `switch` 语句。
- 优缺点
    - 优点：符合开闭原则，增加新产品时只需要添加新的工厂类，不需要修改现有代码。
    - 缺点：增加了类的数量，系统更为复杂。

**示例**：

```java
interface Product {
    void use();
}

class ConcreteProductA implements Product {
    @Override
    public void use() {
        System.out.println("Using Product A");
    }
}

class ConcreteProductB implements Product {
    @Override
    public void use() {
        System.out.println("Using Product B");
    }
}

abstract class Creator {
    public abstract Product factoryMethod();
}

class ConcreteCreatorA extends Creator {
    @Override
    public Product factoryMethod() {
        return new ConcreteProductA();
    }
}

class ConcreteCreatorB extends Creator {
    @Override
    public Product factoryMethod() {
        return new ConcreteProductB();
    }
}

public class Client {
    public static void main(String[] args) {
        Creator creatorA = new ConcreteCreatorA();
        Product productA = creatorA.factoryMethod();
        productA.use();

        Creator creatorB = new ConcreteCreatorB();
        Product productB = creatorB.factoryMethod();
        productB.use();
    }
}
```

### 3. **抽象工厂模式（Abstract Factory Pattern）**

抽象工厂模式是工厂模式的进一步扩展，它提供了一个接口，用于创建一组相关或相互依赖的对象，而无需指定具体的类。与工厂方法模式不同，抽象工厂模式更侧重于一组产品的创建，而不是单个产品的创建。

- 特点
    - 提供一个接口，用来创建相关或依赖的多个产品。
    - 客户端通过抽象工厂来获取一系列的产品对象，而无需知道具体的实现。
- 优缺点
    - 优点：可以方便地更换产品系列（产品的族），符合开闭原则。
    - 缺点：增加了系统的复杂性，如果新增产品族或产品种类时需要修改现有的代码。

**示例**：

```java
interface ProductA {
    void useA();
}

interface ProductB {
    void useB();
}

class ConcreteProductA1 implements ProductA {
    @Override
    public void useA() {
        System.out.println("Using Product A1");
    }
}

class ConcreteProductB1 implements ProductB {
    @Override
    public void useB() {
        System.out.println("Using Product B1");
    }
}

class ConcreteProductA2 implements ProductA {
    @Override
    public void useA() {
        System.out.println("Using Product A2");
    }
}

class ConcreteProductB2 implements ProductB {
    @Override
    public void useB() {
        System.out.println("Using Product B2");
    }
}

interface AbstractFactory {
    ProductA createProductA();

    ProductB createProductB();
}

class ConcreteFactory1 implements AbstractFactory {
    @Override
    public ProductA createProductA() {
        return new ConcreteProductA1();
    }

    @Override
    public ProductB createProductB() {
        return new ConcreteProductB1();
    }
}

class ConcreteFactory2 implements AbstractFactory {
    @Override
    public ProductA createProductA() {
        return new ConcreteProductA2();
    }

    @Override
    public ProductB createProductB() {
        return new ConcreteProductB2();
    }
}

public class Client {
    public static void main(String[] args) {
        AbstractFactory factory1 = new ConcreteFactory1();
        ProductA productA1 = factory1.createProductA();
        ProductB productB1 = factory1.createProductB();
        productA1.useA();
        productB1.useB();

        AbstractFactory factory2 = new ConcreteFactory2();
        ProductA productA2 = factory2.createProductA();
        ProductB productB2 = factory2.createProductB();
        productA2.useA();
        productB2.useB();
    }
}
```

### 总结：

- **简单工厂模式**：由工厂类根据不同的条件决定创建不同的对象，适合产品种类少且变化不大时。
- **工厂方法模式**：通过子类来决定产品的创建，适合产品种类较多时，且产品可能会变化。
- **抽象工厂模式**：提供多个相关的产品的创建接口，适合需要创建一系列相关产品的场景。

