工厂模式
目录
一、从一个披萨店开始
1.1、原先的设计
根据需求,我们首先将最初的披萨店设计成如图所示
当我们需要添加新口味的披萨或者删除销售量不好的披萨时,需要修改源代码,如图所示
我们分析了代码中变化与不变化的地方,并且将变化的部分抽取出来封装
1.2、建立一个简单披萨工厂
根据简单披萨工厂,重新设计PizzaStore类
二、简单工厂的定义
2.1、简单工厂
简单工厂不是一个设计模式,更像是一种编程习惯。
2.2、基于简单工厂设计的类图
2.3、具体代码实现
OrderPizza类
package com.java.choi.pizzastore.simplefactory;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import com.java.choi.pizzastore.pizza.CheesePizza;
import com.java.choi.pizzastore.pizza.GreekPizza;
import com.java.choi.pizzastore.pizza.PepperPizza;
import com.java.choi.pizzastore.pizza.Pizza;
public class OrderPizza {
SimplePizzaFactory mSimplePizzaFactory;
public OrderPizza(SimplePizzaFactory mSimplePizzaFactory) {
setFactory(mSimplePizzaFactory);
}
public void setFactory(SimplePizzaFactory mSimplePizzaFactory) {
Pizza pizza = null;
String ordertype;
this.mSimplePizzaFactory = mSimplePizzaFactory;
do {
ordertype = gettype();
pizza = mSimplePizzaFactory.CreatePizza(ordertype);
if (pizza != null) {
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}
} while (true);
}
private String gettype() {
try {
BufferedReader strin = new BufferedReader(new InputStreamReader(
System.in));
System.out.println("input pizza type:");
String str = strin.readLine();
return str;
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
}
PizzaStore类
package com.java.choi.pizzastore.simplefactory;
public class PizzaStroe {
public static void main(String[] args) {
SimplePizzaFactory mSimplePizzaFactory;
OrderPizza mOrderPizza;
mOrderPizza=new OrderPizza(new SimplePizzaFactory());
}
}
SimplePizzaFactory类
package com.java.choi.pizzastore.simplefactory;
import com.java.choi.pizzastore.pizza.CheesePizza;
import com.java.choi.pizzastore.pizza.GreekPizza;
import com.java.choi.pizzastore.pizza.PepperPizza;
import com.java.choi.pizzastore.pizza.Pizza;
public class SimplePizzaFactory {
public Pizza CreatePizza(String ordertype) {
Pizza pizza = null;
if (ordertype.equals("cheese")) {
pizza = new CheesePizza();
} else if (ordertype.equals("greek")) {
pizza = new GreekPizza();
} else if (ordertype.equals("pepper")) {
pizza = new PepperPizza();
}
return pizza;
}
}
三、加盟披萨店
3.1、加盟店的设计
披萨店的生意日益火爆,有许多商家想加盟披萨店,但是这些商家在不同的区域会导致每家加盟店都想要提供不同风味的披萨。因此我们需要对原有的设计进行重新改造。
我们可以利用SimplePizzaFactory,写出不同的工厂,如NYPizzaFactory、ChicagoPizzaFactory、CalifornizPizzaFactory,那么每个地方都有适合的工厂使用。
当一些商家的加盟店中希望能够采用自己自创的流程制作披萨,那么我们又该如何设计呢?
我们可以将createPizza()方法放回PizzaStore中,并且将其设置为抽象方法,让每个加盟店继承该类并且各自实现自己的制作流程
3.2、具体代码的实现
OrderPizza类
package com.java.choi.pizzastore.method;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import com.java.choi.pizzastore.pizza.CheesePizza;
import com.java.choi.pizzastore.pizza.ChinesePizza;
import com.java.choi.pizzastore.pizza.GreekPizza;
import com.java.choi.pizzastore.pizza.PepperPizza;
import com.java.choi.pizzastore.pizza.Pizza;
public abstract class OrderPizza {
public OrderPizza() {
Pizza pizza = null;
String ordertype;
do {
ordertype = gettype();
pizza = createPizza(ordertype);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
} while (true);
}
abstract Pizza createPizza(String ordertype);
private String gettype() {
try {
BufferedReader strin = new BufferedReader(new InputStreamReader(
System.in));
System.out.println("input pizza type:");
String str = strin.readLine();
return str;
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
}
NYOrderPizza类
package com.java.choi.pizzastore.method;
import com.java.choi.pizzastore.pizza.CheesePizza;
import com.java.choi.pizzastore.pizza.GreekPizza;
import com.java.choi.pizzastore.pizza.NYCheesePizza;
import com.java.choi.pizzastore.pizza.NYPepperPizza;
import com.java.choi.pizzastore.pizza.PepperPizza;
import com.java.choi.pizzastore.pizza.Pizza;
public class NYOrderPizza extends OrderPizza {
@Override
Pizza createPizza(String ordertype) {
Pizza pizza = null;
if (ordertype.equals("cheese")) {
pizza = new NYCheesePizza();
} else if (ordertype.equals("pepper")) {
pizza = new NYPepperPizza();
}
return pizza;
}
}
LDOrderPizza类
package com.java.choi.pizzastore.method;
import com.java.choi.pizzastore.pizza.CheesePizza;
import com.java.choi.pizzastore.pizza.GreekPizza;
import com.java.choi.pizzastore.pizza.LDCheesePizza;
import com.java.choi.pizzastore.pizza.LDPepperPizza;
import com.java.choi.pizzastore.pizza.PepperPizza;
import com.java.choi.pizzastore.pizza.Pizza;
public class LDOrderPizza extends OrderPizza {
@Override
Pizza createPizza(String ordertype) {
Pizza pizza = null;
if (ordertype.equals("cheese")) {
pizza = new LDCheesePizza();
} else if (ordertype.equals("pepper")) {
pizza = new LDPepperPizza();
}
return pizza;
}
}
PizzaStroe
package com.java.choi.pizzastore.method;
public class PizzaStroe {
public static void main(String[] args) {
OrderPizza mOrderPizza;
mOrderPizza=new NYOrderPizza();
}
}
3.3、声明一个工厂方法
原本是一个由对象负责所有具体类的实例化,现在通过对PizzaStore做的改变,变成由子类负责实例化
四、认识工厂方法模式
4.1、工厂方法模式的定义
所有的工厂模式都是用来封装对象的创建。工厂方法模式通过让子类决定该创建的对象是什么,来达到将对象创建的过程封装的目的。以披萨店为例子,里面包含的组成元素有:
工厂方法模式的正式定义
4.2、一个依赖性比较强的披萨店
假如没有使用工厂模式,那么我们设计出来的披萨店将会是如图所示
如果将这个版本的披萨店和它依赖的对象画成图的形式,将会非常的乱
而我们采用工厂模式的设计,如图所示
4.3、工厂模式中的设计原则
对比依赖性强的披萨店与我们使用工厂模式的披萨店,我们将会发现代码里减少对具体类的依赖是件“好事”|,因此从中我们引出一条非常重要的设计原则
a、要依赖抽象,不要依赖具体类(依赖倒置原则)
五、对披萨店原料的思考
披萨店成功的关键在于新鲜、高质量的原料,那么我们如何保证原料的新鲜?如对于加盟在不同区域的店,不同区域的酱料不一样,因此我们要对我们的原本的设计进行改造。
5.1、建造原料工厂
纽约原料工厂
5.2、重做披萨
5.3、回到披萨店
5.4、我们做了什么?
我们引入了新型的工厂,也就是抽象工厂,来创建披萨原料家族,通过抽象工厂所提供的接口,可以创建产品的家族,利用这个接口书写代码,我们可以从实际的工厂解耦,以便在不同上下文中实现各式各样的产品。
六、抽象工厂模式
6.1、定义抽象工厂模式
6.2、加盟披萨店的类图