《Head first设计模式》中使用比萨做例子,我们这里也都用比萨举例。我们假设要开一家比萨店。
工厂模式产生的压力主要来自于增加更多类型的比萨类。同时避免直接实例化对象,因为我们设计程序时应该面向接口编程。这样会让程序更容易维护和扩展,使其更有弹性。
定义:工厂方法方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
遵守的原则:依赖倒置原则,就是要依赖抽象,不要依赖具体类。这个原则比“针对接口编程”更加“抽象”。这个原则说明了:不能让高层组件依赖低层组件,而且,不管高层组件或低层组件,“两者”都应该依赖于抽象。其中的关系,如下图所示:
现在通过结合程序来解释工厂模式。我们需要两个工厂,一个是比萨工厂,另一个是原料工厂。之间的类图关系如下:
根据类图分析程序:
一、首先我们需要有三个抽象,Pizza、PizzaStore、PizzaIngredientFactory,它们分别代表比萨、比萨工厂、原料工厂。代码如下:
*
* 从一个抽象比萨开始,所有的具体比萨都必须派生自这个类。
*/
public abstract class Pizza
{
String name;
//每一个比萨都持有一组在准备时会用到的原料
Dough dough;
Sauce sauce;
Veggies veggies[];
Cheese cheese;
Pepperoni pepperoni;
Clams clam;
/**
* 把prepare()方法声明成抽象。在这个方法中,我们需要收集比萨所需的原料,
* 而这些原料当然是来自原料工厂了。
*/
abstract void prepare();
public void bake()
{
System.out.println("baking");
}
public void cut()
{
System.out.println("cutting");
}
public void box()
{
System.out.println("box");
}
public void setName(String name)
{
this.name=name;
}
public String getName()
{
return name;
}
}
*
* PizzaStore作为超类,让每个域类型(NYPizzaStore)都继承这个
* PizzaStore,每个子类各自决定如何制造比萨。
*/
public abstract class PizzaStore
{
/**
* 每个子类都必须自己实现createPizza方法
* @param type
* @return
*/
protected abstract Pizza createPizza(MenuList type);
}
public interface PizzaIngredientFactory
{
/**
* 在接口中,每个原料都有一个对应的方法创建该原料。
*这里的每一个原料都是一个类。
*/
public Dough createDough();
public Sauce createSauce();
public Cheese createCheese();
public Veggies[] createVeggies();
public Pepperoni createPepperoni();
public Clams createClam();
}
二、有了抽象后我们要分别实现抽象。
public class ClamPizza extends Pizza
{
PizzaIngredientFactory ingredientFactory;
public ClamPizza(PizzaIngredientFactory ingredientFactory)
{
this.ingredientFactory=ingredientFactory;
}
public void prepare()
{
System.out.println("Preparing "+name);
dough=ingredientFactory.createDough();
sauce=ingredientFactory.createSauce();
cheese=ingredientFactory.createCheese();
clam=ingredientFactory.createClam();
}
}
public class NYPizzaStore extends PizzaStore
{
public Pizza createPizza(MenuList item)
{
Pizza pizza=null;
//纽约店会用纽约比萨原料工厂的原料
PizzaIngredientFactory ingredientFactory=new NYPizzaIngredientFactory();
if(item==MenuList.Cheese)
{
pizza=new CheesePizza(ingredientFactory);//把工厂传递给每一个比萨,以便比萨能从工厂中取得原料
pizza.setName("New York Style Cheese Pizza");
}else if(item==MenuList.Veggie)
{
pizza=new VeggiePizza(ingredientFactory);
pizza.setName("New York Style Veggie Pizza");
}else if(item==MenuList.Clam)
{
pizza=new ClamPizza(ingredientFactory);
pizza.setName("New York Style Clam Pizza");
}else if(item==MenuList.Pepperoni)
{
pizza=new PepperoniPizza(ingredientFactory);
pizza.setName("New York Style Pepperoni Pizza");
}
if(pizza!=null)
{
System.out.println(pizza.getName());
}
return pizza;
}
}
*
* 具体原料工厂必须实现这个接口。
*/
public class NYPizzaIngredientFactory implements PizzaIngredientFactory
{
/**
* 为原料家族中的每一种原料都提供了纽约版本
*/
public Dough createDough()
{
return new ThinCrustDough();
}
public Sauce createSauce()
{
return new MarinaraSauce();
}
public Cheese createCheese()
{
return new ReggianoCheese();
}
public Veggies[] createVeggies()
{
Veggies veggies[]={new Garlic(),new Onion(),new Mushroom(),new RedPepper()};
return veggies;
}
public Pepperoni createPepperoni()
{
return new SlicedPepperoni();
}
public Clams createClam()
{
return new FreshClams();
}
}
public static void main(String[] args)
{
PizzaStore nyStore=new NYPizzaStore();
Pizza pizza=nyStore.createPizza(MenuList.Cheese);
Pizza pizzaVeggie=nyStore.createPizza(MenuList.Veggie);
}