2. 简单工厂模式

145 阅读4分钟

一. 简单工厂模式

简单工厂模式是一种创建型模式。本质上就是一个工厂,根据用户需要的产品类型,来创建指定类型的产品。因为在简单工厂模式中用于创建实例的方法是静态方法,因此简单工厂模式又被称为静态工厂方法模式

介绍简单工厂模式之前我们通过一个披萨项目来引出问题,然后给出简单工厂模式这种解决方案;然后随着披萨项目遇到的后续问题,我们给出新的解决方案工厂方法模式和最终的解决方案抽象工厂模式

二. 披萨项目

我现在有一个披萨店,目前卖两种口味的披萨,GreekPizzaCheesePizza,每个披萨都有prepare(),bake(),cut(),box()这4种步骤,原料、烘焙、切割、打包。我们把这个过程抽象出来,其实就是一个抽象的Pizza类,以及两个子类产品GreekPizza和CheesePizza。

1. Pizza披萨抽象类
public abstract class Pizza{
  //四个抽象方法
  public abstract void prepare();
  public abstract void bake();
  public abstract void cut();
  public abstract void box();
}
2. GreekPizza披萨类
public class GreenPizza extends Pizza{
   public void prepare(){
       System.out.println("开始准备GreenPiazza");
   } 
   public void bake(){
       System.out.println("正在烤GreenPiazza");
   } 
   public void cut(){
       System.out.println("正在切GreenPiazza");
   } 
   public void box(){
       System.out.println("正在打包GreenPiazza");
   } 
}
3. CheesePizza披萨类
public class CheesePizza extends Pizza{
   public void prepare(){
       System.out.println("开始准备CheesePizza");
   } 
   public void bake(){
       System.out.println("正在烤CheesePizza");
   } 
   public void cut(){
       System.out.println("正在切CheesePizza");
   } 
   public void box(){
       System.out.println("正在打包CheesePizza");
   }
}

三. 此时客户如何下单呢?

客户下单的时候会选择对应的Pizza类型,店长就会根据Pizza类型去创建对应的Pizza,客户端是暴露给用户来使用的,自然我们不希望暴露给外部使用的接口来回变动

public class PizzaClient {
    // 根据订单类型创建对应的Pizza
    public void OrderPizza(String orderType) {
        Pizza pizza = null;
        orderType = getType();
        if (orderType.equals("greek")) {
            pizza = new GreekPizza();
            pizza.setName("希腊披萨");
        } else if (orderType.equals("cheese")) {
            pizza = new CheesePizza();
            pizza.setName("奶酪披萨");
        } else {
            break;
        }
            //输出pizza制作过程
            pizza.prepare();
            pizza.bake();
            pizza.cut();
            pizza.box();
}

四. 引出问题

问题:现在有一种新的FruitPizza非常流行,如果我们想要新增这种类型的Pizza要怎么做?

解答:目前的方案需要创建FruitPizza去实现Pizza抽象类,然后不得不修改我们暴露给用户使用的客户端

我们就需要在客户端中修改逻辑,新增上FruitPizza类型

if(orderType.equals("fiuit")){
    pizza = new FruitPizza();
    pizza = new FruitPizza();
    pizza.setName("水果披萨");
}

场景:我们将来可能新增各种类型的Pizza,或者有些Pizza不流行我们不卖了怎么办?

问题:我们不得不多次修改暴露给用户使用的客户端代码!违背了开闭原则,我们对修改应该是封闭的呀!

解决方案:引用工厂,将逻辑的修改封装在工厂中,对外客户端不进行修改

五. 引入工厂

流程:客户端orderPizza --> 工厂createPizaa --> 生产具体的Pizza

(1)Pizza的生产从客户端变成了工厂,将来Pizza的增删改查都在工厂中完成
(2)客户端暴露给用户,只负责下单,对外暴露的服务就不用在变动了

我们现在梳理一下,简单工厂模式中出现了哪些角色:

1.客户端(PizzaClient):暴露给外部使用的服务,原则上不应该有服务实现,只提供服务接口

2.工厂类(Factory):负责产品的增删改查(服务的具体实现逻辑),不暴露给外部用户

3.抽象产品(Pizza):抽象产品类是由简单工厂模式所创建的产品对的父类或接口

4.具体产品(FruitPizza):简单工厂模式所创建的对象

六. 简单工厂的实现

1. 工厂类实现
//SimplePizzaFactory是我们的新类,它只做一件事:帮它的客户创建披萨
public class SimplePizzaFactory{
    //所有客户用这个方法CreatePizza实例化新对象
    //想要不同口味的披萨就传入不同的参数
    public static Pizza CreatePizza(String orderType){
        Pizza pizza = null;
        if(orderType.equals("cheese")){
            pizza = new CheesePizza();
        }else if(orderType.equals("greek")){
            pizza = new GreekPizza();
        }if(orderType.equals("fiuit")){
            pizza = new FruitPizza();
        }
        return pizza;
    }
    //SimplePizzaFactory可以拥有多个客户(方法)
    ......
}
2. 客户端实现
public class PizzaClient {
    // 根据订单类型创建对应的Pizza,只负责下单到工厂,工厂生产Pizza给用户
    public void OrderPizza(String orderType) {
        Pizza pizza = null;
        pizza = SimplePizzaFactory.CreatePizza(orderType);
}

七. 总结与思考

总结:

简单工厂模式满足了开闭原则,我们暴露给外部的服务不再有服务实现逻辑了,只对外提供服务接口,不提供服务实现,具体的服务实现放在工厂中,不会对用户暴露。

可是:如果我们的业务逻辑过于复杂呢?简单工厂模式还能满足吗?一个工厂负责所有业务逻辑,如果业务逻辑特别复杂怎么办?这个工厂类出错了,整个业务是不是就废了呢?

思考:我将来要在世界各地开分店,一个工厂还够用吗?世界各地对Pizza的口味爱好都不一样,我要怎么办呢?现在工厂只能生产Pizza,但是我还想让他生产点别的东西怎么办呀?

八. 最后送给大家一张大图

image.png