这篇文章是对三个工厂模式的分析总结,把三个放在一起希望可以帮到大家更好的理解工厂模式。本文的例子选用的是《head first 设计模式》一书中的披萨店。
问题描述:一个披萨店里有芝士披萨和蔬菜披萨,客人到店里买预定披萨,可能你的代码会这么写:
public void orderPizza(String type){
Pizza pizza = null;
if (type.equals("cheese")){
pizza = new CheesePizza();
}else if (type.equals("veggie")){
pizza = new VeggiePizza();
}
if (pizza != null){
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}
}
如果你要添加店里的披萨口味,那你需要添加更多的if else,如果有些口味销量不好,那你有需要去删除多余的if else;这样频繁的修改明显不是我们想要的。这里就要用到简单工厂模式了。
简单工厂模式
定义:又叫做静态工厂方法模式,是由一个工厂对象决定创建出哪一种产品类的实例。
下面先给出uml类图
添加了一个新的工厂类,通过工厂类的createPizza()方法来制作客户需要的披萨具体的代码如下:
SimplePizzaFactory:
public class SimplePizzaFactory {
public static Pizza createPizza(String type){
Pizza pizza = null;
if (type.equals("cheese")){
pizza = new CheesePizza();
}else if (type.equals("veggie")){
pizza = new VeggiePizza();
}
return pizza;
}
}
写一个披萨的抽象类,所有的披萨继承这个抽象类,我把披萨的切割和包装当做是不变的步骤,不同的披萨准备方法和烘焙方法不一样。
Pizza:
public abstract class Pizza {
public abstract void prepare();
public abstract void bake();
public void cut(){
System.out.println("cut pizza");
};
public void box(){
System.out.println("cut pizza");
};
}
CheesePizza:
public class CheesePizza extends Pizza{
@Override
public void prepare() {
System.out.println("prepare CheesePizza");
}
@Override
public void bake() {
System.out.println("bake CheesePizza");
}
}
VeggiePizza:
public class VeggiePizza extends Pizza{
@Override
public void prepare() {
System.out.println("prepare VeggiePizza");
}
@Override
public void bake() {
System.out.println("bake VeggiePizza");
}
}
PizzaStore:
public class PizzaStore {
public void orderPizza(String type){
Pizza pizza;
pizza = SimplePizzaFactory.createPizza(type);
if (pizza != null){
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}
}
public static void main(String[] args) {
PizzaStore pizzaStore = new PizzaStore();
pizzaStore.orderPizza("cheese");
pizzaStore.orderPizza("veggie");
}
}
截图:
到这里算是解决一开始提到的频繁修改问题,接下来披萨店有了新的需求,披萨店要在芝加哥和纽约开分店,但是芝加哥和纽约地区不同口味也会不同。接下来就要通过工厂方法模式来解决问题。
工厂方法模式
uml类图:
这里修改了PizzaStore类,新增了NYPizzaStore和ChicagoPizzaStore
代码如下:
Pizza:
public abstract class Pizza {
public abstract void prepare();
public abstract void bake();
public void cut(){
System.out.println("cut pizza");
};
public void box(){
System.out.println("cut pizza");
};
}
NYStyleVeggiePizza:
public class NYStyleVeggiePizza extends Pizza{
@Override
public void prepare() {
System.out.println("prepare NYStyleVeggiePizza");
}
@Override
public void bake() {
System.out.println("bake NYStyleVeggiePizza");
}
}
NYStyleCheesePizza:
public class NYStyleCheesePizza extends Pizza{
@Override
public void prepare() {
System.out.println("prepare NYStyleCheesePizza");
}
@Override
public void bake() {
System.out.println("bake NYStyleCheesePizza");
}
}
PizzaStore:
/**
* Created by zhaoyigang on 2017/6/3.
*/
public abstract class PizzaStore {
protected abstract Pizza createPizza(String type);
public void orderPizza(String type){
Pizza pizza;
pizza = createPizza(type);
if (pizza != null){
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}
}
public static void main(String[] args) {
ChicagoPizzaStore chicagoPizzaStore = new ChicagoPizzaStore();
chicagoPizzaStore.orderPizza("cheese");
NYPizzaStore nyPizzaStore = new NYPizzaStore();
nyPizzaStore.orderPizza("veggie");
}
}
ChicagoPizzaStore:
public class ChicagoPizzaStore extends PizzaStore{
@Override
protected Pizza createPizza(String type) {
if (type.equals("cheese")){
return new ChicagoStyleCheesePizza();
}else if (type.equals("veggie")){
return new ChicagoStyleVeggiePizza();
}
return null;
}
}
NYPizzaStore:
public class NYPizzaStore extends PizzaStore{
@Override
protected Pizza createPizza(String type) {
if (type.equals("cheese")){
return new NYStyleCheesePizza();
}else if (type.equals("veggie")){
return new NYStyleVeggiePizza();
}
return null;
}
}
截图:
相比之下,简单工厂模式只有一个工厂,工厂方法模式对每一个产品都有相应的工厂。纽约和芝加哥的披萨店分别有不同的工厂,生产不同口味的披萨,满足不同客户的需求。
如果要确保每个披萨店的原料标准化,打算建造一个原料生产的工厂,并将原料运送到各家加盟店。那么就要用到抽象工厂方法了。
抽象工厂方法
定义:为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。
UML类图:
代码如下:
Pizza:
public abstract class Pizza {
private Materiel materiel;
public abstract void prepare();
public abstract void bake();
public void cut(){
System.out.println("cut pizza");
}
public void box(){
System.out.println("box pizza");
}
}
CheesePizza:
public class CheesePizza extends Pizza{
private MaterielFactory materielFactory;
public CheesePizza(MaterielFactory materielFactory){
this.materielFactory = materielFactory;
}
@Override
public void prepare() {
materielFactory.createMateriel();
System.out.println("prepare cheesePizza");
}
@Override
public void bake() {
System.out.println("bake cheesePizza");
}
}
MaterielFactory:
public interface MaterielFactory {
public Materiel createMateriel();
}
NYMaterielFactory:
public class NYMaterielFactory implements MaterielFactory{
@Override
public Materiel createMateriel() {
System.out.println("prepare NYPizzaMateriel");
return new NYPizzaMateriel();
}
}
ChicagoMaterielFactory:
public class ChicagoMaterielFactory implements MaterielFactory{
@Override
public Materiel createMateriel() {
System.out.println("prepare ChicagoPizzaMateriel");
return new ChicagoPizzaMateriel();
}
}
PizzaStore:
public abstract class PizzaStore {
protected abstract Pizza createPizza(String type);
public void orderPizza(String type){
Pizza pizza;
pizza = createPizza(type);
if (pizza != null){
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
System.out.println("finished");
System.out.println("***************");
}
}
public static void main(String[] args) {
ChicagoPizzaStore chicagoPizzaStore = new ChicagoPizzaStore();
chicagoPizzaStore.orderPizza("cheese");
NYPizzaStore nyPizzaStore = new NYPizzaStore();
nyPizzaStore.orderPizza("veggie");
}
}
ChicagoPizzaStore:
public class ChicagoPizzaStore extends PizzaStore{
@Override
protected Pizza createPizza(String type) {
ChicagoMaterielFactory chicagoMaterielFactory = new ChicagoMaterielFactory();
if (type.equals("cheese")){
return new CheesePizza(chicagoMaterielFactory);
}else if (type.equals("veggie")){
return new VeggiePizza(chicagoMaterielFactory);
}
return null;
}
}
NYPizzaStore:
public class NYPizzaStore extends PizzaStore{
@Override
protected Pizza createPizza(String type) {
NYMaterielFactory materielFactory = new NYMaterielFactory();
if (type.equals("cheese")){
return new CheesePizza(materielFactory);
}else if (type.equals("veggie")){
return new VeggiePizza(materielFactory);
}
return null;
}
}
相比之下,工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。