1. 简单工厂模式

简单工厂模式也称为静态工厂模式,就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建。比如,我们一个车工厂,我们只要告诉他们我需要什么车(宝马、特斯拉),它就会给你生产一辆车,我们不需要关注车是怎么来的,只需要告诉它你的需求。

优点:

  • 简单易于实现。
  • 把类的实例化交给工厂,易于解耦。

缺点:

  • 添加具体产品需要修改工厂违反 OCP 开放封闭原则(对外扩展开放,对修改关闭)。 ```java public interface Car { void name(); }

public class WuLing implements Car{ @Override public void name() { System.out.println(“五菱宏光”); } }

public class Tesla implements Car{ @Override public void name() { System.out.println(“特斯拉”); } }

public class CarFactory { public static Car getCar(String car) { if (Objects.equals(“五菱”, car)) { return new WuLing(); } else if (Objects.equals(“特斯拉”, car)) { return new Tesla(); } else if (Objects.equals(“大众”, car)) { return new DaZhong(); } else { return null; } } }

public class Consumer { public static void main(String[] args) { Car car1 = CarFactory.getCar(“五菱”); car1.name();

  1. Car car2 = CarFactory.getCar("特斯拉");
  2. car2.name();
  3. }

}


---

<a name="r5lS2"></a>
# 2. 工厂方法模式
工厂方法模式,在不修改已有类的前提下,为每个产品提供一个工厂类,这些工厂类都实现了共同的接口,在客户端判断使用哪个工厂类来创建对象。如果我们要增加一个产品,需要在代码中添加对应的产品类和工厂类。<br />优点:

- 实现了开放封闭原则,每次添加子产品不需要修改原有代码,只需要创建相应的产品类和工厂类。
- 降低了代码耦合度。

缺点:

- 增加了代码量,每个具体产品都需要一个具体工厂。
- 当增加抽象产品,也就是添加一个其他产品族,需要修改工厂,违背了OCP。
```java
public interface CarFactory {
    Car getCar();
}

public class WuLingFactory implements CarFactory{
    @Override
    public Car getCar() {
        return new WuLing();
    }
}

public class Consumer {
    public static void main(String[] args) {
        Car car1 = new WuLingFactory().getCar();
        car1.name();
    }
}

3. 抽象工厂模式

抽象工厂模式,可以理解为,当工厂只生产一个产品的时候,即为工厂方法模式,而工厂如果生产两个或以上的商品即变为抽象工厂模式。我们在抽象工厂接口中新增创建系统的方法,并由实例工厂类去实现。这个工厂称为超级工厂,不可以增加产品,可以增加产品族。

产品族:手机、路由就各是一个产品族。
产品等级:简单来说就是同一类产品,比如小米手机、华为手机等都是手机。

//手机产品接口
public interface IphoneProduct {
    void start();
    void shutdown();
    void callup();
    void sendMS();
}

//路由器产品接口
public interface IRouteProduct {
    void start();
    void shutdown();
    void openWifi();
    void setting();
}

//小米手机产品
public class XiaomiPhone implements IphoneProduct{
    。。。
}


//小米工厂
public class XiaomiProductFactory implements IProductFactory{
    @Override
    public IphoneProduct iphoneProduct() {
        return new XiaomiPhone();
    }

    @Override
    public IRouteProduct irouteProduct() {
        return new XiaomiRouter();
    }
}

//抽象产品工厂
public interface IProductFactory {
    //生产手机
    IphoneProduct iphoneProduct();

    //生产路由器
    IRouteProduct irouteProduct();
}

public class Client {
    public static void main(String[] args) {
        System.out.println("===============小米系列产品===========");
        IphoneProduct xiaomiPhone = new XiaomiProductFactory().iphoneProduct();
        xiaomiPhone.callup();
        IRouteProduct xiaomiRouter = new XiaomiProductFactory().irouteProduct();
        xiaomiRouter.openWifi();
    }
}

原型图
image.png


4. 三者的区别

  • 简单工厂模式:就是说你要什么产品,由对应的工厂创建(即 new 工厂对象调用方法返回对应的产品对象)。
    • 优点:简单易于实现。
    • 但添加产品需要修改工厂违反了 OCP 开闭原则。
  • 工厂方法模式:就是说为每个产品提供一个工厂类,由客户端决定使用哪个工厂类创建产品。
    • 优点:实现了开放封闭原则,每次添加子产品不需要修改原有代码,只需要创建相应的产品类和工厂类,降低了代码耦合度。
    • 缺点:增加了代码量,并且当增加抽象产品,也就是添加一个其他产品族,需要修改工厂,违背了OCP。
  • 抽象工厂模式:可以理解为,当工厂只生产一个产品的时候,即为工厂方法模式,而工厂如果生产两个或以上的商品即变为抽象工厂模式。我们在抽象工厂接口中新增创建系统的方法,并由实例工厂类去实现,不可以增加产品,可以增加产品族。(产品族:小米手机、小米路由器就是一个产品族)。
    • 优点:具体产品在应用层的代码隔离,无需关心创建的细节,并且可以将一系列的产品统一到一起创建。
    • 缺点:规定了所有可能被创建的产品集合,扩展产品族相当麻烦,而且扩展产品族会违反 OCP。
    • 适用场景:客户端不依赖于产品类实例如何被创建、实现等细节;强调一系列相关的产品对象(属于同一产品族)一起适用创建对象需要大量的重复代码。

举例说明:比如说我们的超级工厂里实现了手机这个产品族,再增加个路由器产品族,我们需要定义一个路由器产品的接口,并通过某一种产品实现(比如小米路由器),并且还需要到小米工厂(实现了超级工厂)里去加上路由器的生产,即由小米工厂生产这个小米路由器。


5. 应用场景

工厂模式:

  • JDBC 中的 Connection 对象的获取。
  • 使用 mybatis 里面经常用到的 sqlSessionFactory.openSession(ExecutorType.BATCH);,用的就是工厂模式,实际上用的是 Defaultsqlsession 里的 openSession 方法。
  • Spring使用工厂模式可以通过 BeanFactory 或 ApplicationContext 创建 bean 对象。

单例模式:用于 Runtime,Calendar 和其他的一些类中。