一. 简单工厂模式
简单工厂模式
是一种创建型模式。本质上就是一个工厂,根据用户需要的产品类型,来创建指定类型的产品。因为在简单工厂模式中用于创建实例的方法是静态方法,因此简单工厂模式又被称为静态工厂方法模式
。
介绍简单工厂模式之前我们通过一个披萨项目来引出问题,然后给出简单工厂模式
这种解决方案;然后随着披萨项目遇到的后续问题,我们给出新的解决方案工厂方法模式
和最终的解决方案抽象工厂模式
。
二. 披萨项目
我现在有一个披萨店,目前卖两种口味的披萨,GreekPizza
和CheesePizza
,每个披萨都有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,但是我还想让他生产点别的东西怎么办呀?