标签 设计模式
 标签 工厂模式
 分类 Java
 分类 开源项目

死磕设计模式—工厂模式

前言(八问知识体系)

死磕设计模式-工厂模式

1.1.简介

  • 简单工厂模式属于创建型模式,属于工厂模式中的一种,简单工厂模式就是由一个工厂对象来决定创建出一种具体的产品
  • 在简单工厂模式中,我们会定义一个创建对象的类,多使用反射的方法来创建具体产品实例,这个类用来封装实例化对象的行为
  • 在软件开发中,当我们需要大量的创某种,某类或者某一批对象时候,就可以考虑使用简单工厂模式

1.2.为什么出现工厂模式

如果用传统方式生产披萨,那么实现的类图如下:

image-20191026212645117

如果,我们增加披萨的种类,在增加生产披萨的商店,那么类图如下

image-20191026213232154

1.3.简单工厂模式

很明显,从上面的的类图中我们就可以看出这种实现方法违背啦设计模式中的对扩展开放,对修改关闭的原则,当我们要增加一个新的披萨种类时,我们需要修改所有的生产披萨商店的代码,从类图中我们就可以看出生产披萨的商店和披萨之间耦合太严重,于是前辈们总结啦一种约定俗成的实现套路,即工厂模式类图如下:

image-20191026220852997

将创建对象的行为封装到一个类中,当有新的种类加入时候只需要修改改类即可,其它创建对象的地方则不需要修改,这就是简单工厂模式

当我们只需要一个工厂就能满足需求的时候,我们可以简化工厂模式,将创建对象的方法该用静态方法,这就是静态工厂模式

image-20191026221529976

1.4.简单工厂模式实例

抽象产品类

public interface Pizza {

    /**
     * prepare
     *
     * @description 披萨的抽象准备方法
     * @author luokangyuan
     * @date 2019/10/26 14:00
     * @version 1.0.0
     */
    void prepare();
}

具体产品类

@Slf4j
@NoArgsConstructor
public class CheesePizza implements Pizza {

    @Override
    public void prepare() {
      log.info("芝士披萨开始准备...");
    }
}

简单工厂类(实现方式一—枚举)

@Slf4j
public class SimpleFactory {
    /**
     * createPizza
     *
     * @description 创建具体产品
     * @param pizzaEnum : 产品枚举
     * @return 具体的产品实例
     * @author luokangyuan
     * @date 2019/10/26 22:59
     * @version 1.0.0
     */
    public static Pizza createPizza(PizzaEnum pizzaEnum) {
        return pizzaEnum.getConstructor().get();
    }
}

产品枚举类

public enum PizzaEnum {

    CHEESE(CheesePizza::new),

    FRUIT(FruitPizza::new);

    private final Supplier<Pizza> constructor;

    PizzaEnum(Supplier<Pizza> constructor) {
        this.constructor = constructor;
    }

    public Supplier<Pizza> getConstructor() {
        return constructor;
    }

}

客户端调用

public static void main(String[] args) {
    Pizza cheesePizza = SimpleFactory.createPizza(PizzaEnum.CHEESE);
    Pizza fruitPizza = SimpleFactory.createPizza(PizzaEnum.FRUIT);
    cheesePizza.prepare();
    fruitPizza.prepare();
}

简单工厂类(实现方式二—反射)

public static <T extends Pizza> T createPizza1(Class<T> t) {
    Pizza pizza = null;
    try {
        pizza = (Pizza) Class.forName(t.getName()).newInstance();
    } catch (Exception e) {
        log.error("生产披萨出错", e);
    }
    return (T) pizza;
}

客户端调用

CheesePizza cheesePizza1 = SimpleFactory.createPizza1(CheesePizza.class);
FruitPizza fruitPizza1 = SimpleFactory.createPizza1(FruitPizza.class);
cheesePizza1.prepare();
fruitPizza1.prepare();

1.5.工厂方法模式

在简单工厂模式中,我们是将对象的创建实现在工厂类中,如果,存在不同的工厂,每个工厂的实例化对象方法不一样,此时就出现啦工厂方法模式,简单将就是工厂定义创建产品的抽象方法,将产品的具体实例化推到子类去实现,还是以订购披萨为例,类图如下:

image-20191027112238261

1.6.工厂方法模式实例

抽象产品

public interface IPizza {
    /**
     * getPizzaName
     *
     * @description 获取披萨名称
     * @return 披萨名称
     * @author luokangyuan
     * @date 2019/10/27 11:43
     * @version 1.0.0
     */
    String getPizzaName();

    /**
     * getPizzaName
     *
     * @description 获取披萨价格
     * @return 披萨价格
     * @author luokangyuan
     * @date 2019/10/27 11:43
     * @version 1.0.0
     */
    Double getPrice();
}

具体产品实现类

public class BjCheesePizza  implements IPizza{

    @Override
    public String getPizzaName() {
        return "北京芝士披萨";
    }

    @Override
    public Double getPrice() {
        return 9999.99;
    }
}
public class ShCheesePizza implements IPizza {
    @Override
    public String getPizzaName() {
        return "上海芝士披萨";
    }

    @Override
    public Double getPrice() {
        return 8888.88;
    }
}

抽象工厂

public interface ICreateFactory {
	/**
     * getICreatePizza
     *
     * @description 获取披萨
     * @return 具体的披萨
     * @author luokangyuan
     * @date 2019/10/27 11:49
     * @version 1.0.0
     */
    IPizza getICreatePizza();
}

具体工厂实现

public class BjPizzaFactory implements ICreateFactory{

    @Override
    public IPizza getICreatePizza() {
        return new BjCheesePizza();
    }
}
public class ShPizzaFactory implements ICreateFactory {
    @Override
    public IPizza getICreatePizza() {
        return new ShCheesePizza();
    }
}

客户端调用

 public static void main(String[] args) {
     ICreateFactory bjPizzaFactory = new BjPizzaFactory();
     ICreateFactory shPizzaFactory = new ShPizzaFactory();
     IPizza iCreatePizza = bjPizzaFactory.getICreatePizza();
     IPizza iCreatePizza1 = shPizzaFactory.getICreatePizza();
     log.info("你选择啦{},价格为:{}", iCreatePizza.getPizzaName(), iCreatePizza.getPrice());
     log.info("你选择啦{},价格为:{}", iCreatePizza1.getPizzaName(), iCreatePizza1.getPrice());
 }

实例代码使用idea查看的类图如下:

image-20191027120215414

1.7.抽象工厂模式

抽象工厂模式实际是将简单工厂模式和工厂方法模式进行类一个整合,其类图如下:

image-20191027121620781

1.8.总结和使用场景

  • 工厂模式的意义就是将实例化对象的行为提取出来,放在一个类中统一的管理和维护。

  • 符合设计原则中的依赖抽象的原则。

  • 在使用对象的时候,我们依赖的接口中的抽象方法。

  • JDK中的java.util.Calendar#getInstance()使用了抽象工厂模式。

  • JDK中的java.lang.Object#toString()使用了工厂方法模式。

  • Spring中的FactoryBean使用了工厂方法模式。

  • Mybatis中的SqlSessionFactory使用了工厂方法模式。

目录