工厂模式(1)
假设你有个披萨店,为客人提供各式各样的披萨:
假使制作并递送披萨的流程如下:主要由prepare,bake,box三个流程组成:
package javaapplication2;
public class Main
{
public static void main(String[] args)
{
orderPizza();
}
static public Pizza orderPizza()
{
Pizza pizza = new Pizza();
pizza.prepare();
pizza.bake();
pizza.box();
return pizza;
}
}
class Pizza
{
public void prepare()
{
System.out.println("pizza prepared");
}
public void bake()
{
System.out.println("pizza baked");
}
public void box()
{
System.out.println("pizza boxed");
}
}
上面的orderPizza函数有些奇怪,我们把它从客户端Main中分离出去,让一个PizzaStore类专门负责orderPizza:
package javaapplication2;
public class Main
{
public static void main(String[] args)
{
PizzaStore.orderPizza();
}
}
class PizzaStore
{
static public Pizza orderPizza()
{
Pizza pizza = new Pizza();
pizza.prepare();
pizza.bake();
pizza.box();
return pizza;
}
}
class Pizza
{
public void prepare()
{
System.out.println("pizza prepared");
}
public void bake()
{
System.out.println("pizza baked");
}
public void box()
{
System.out.println("pizza boxed");
}
}
现在披萨店必须加工生产各式各样的披萨,所以我们用一个stract class Pizza 类来封装所有披萨相同的功能,比如prepare,bake, box,再用各种子类继承之,来实现各自的特性,如下:
package javaapplication2;
public class Main
{
public static void main(String[] args)
{
PizzaStore.orderPizza();
}
}
class PizzaStore
{
static public Pizza orderPizza()
{
Pizza pizza = new CheesePizza();
pizza.prepare();
pizza.bake();
pizza.box();
return pizza;
}
}
abstract class Pizza
{
public void prepare()
{
System.out.println("pizza prepared");
}
public void bake()
{
System.out.println("pizza baked");
}
public void box()
{
System.out.println("pizza boxed");
}
}
class CheesePizza extends Pizza
{
@Override
public void prepare()
{
System.out.println("CheesePizza prepared");
}
}
class ClamPizza extends Pizza
{
@Override
public void prepare()
{
System.out.println("ClamPizza prepared");
}
}
我们看到,上面的orderPizza()方法中有一个new方法是会随情况改变的,我们让变化在客户端Main中发生,而让该类保持稳定:即根据Main函数中字符串给的不同,而自动产生和递送不同种类的披萨。
package javaapplication2;
public class Main
{
public static void main(String[] args)
{
PizzaStore.orderPizza("ClamPizza");
}
}
class PizzaStore
{
static public Pizza orderPizza(String pizzaType)
{
Pizza pizza;
if (pizzaType.equals("CheesePizza"))
{
pizza = new CheesePizza();
}
else if (pizzaType.equals("ClamPizza"))
{
pizza = new ClamPizza();
}
else
{
throw new UnsupportedOperationException("no such pizza");
}
pizza.prepare();
pizza.bake();
pizza.box();
return pizza;
}
}
abstract class Pizza
{
public void prepare()
{
System.out.println("pizza prepared");
}
public void bake()
{
System.out.println("pizza baked");
}
public void box()
{
System.out.println("pizza boxed");
}
}
class CheesePizza extends Pizza
{
@Override
public void prepare()
{
System.out.println("CheesePizza prepared");
}
}
class ClamPizza extends Pizza
{
@Override
public void prepare()
{
System.out.println("ClamPizza prepared");
}
}
当Pizza的子类增加时(即pizza的品种增加时),显然上面的orderPizza(本来我们是希望它保持稳定的,让Main变动)中的if..else…就需要继续增加,在整个orderPizza方法中,只有这部分是变动的,我们把它提取出来:让一个“工厂”专门生产pizza,即专门new披萨。
package javaapplication2;
public class Main
{
public static void main(String[] args)
{
PizzaStore.orderPizza("ClamPizza");
}
}
class PizzaStore
{
static public Pizza orderPizza(String pizzaType)
{
Pizza pizza = PizzaFactory.createPizza(pizzaType);
pizza.prepare();
pizza.bake();
pizza.box();
return pizza;
}
}
class PizzaFactory
{
static public Pizza createPizza(String pizzaType)
{
Pizza pizza;
if (pizzaType.equals("CheesePizza"))
{
pizza = new CheesePizza();
}
else if (pizzaType.equals("ClamPizza"))
{
pizza = new ClamPizza();
}
else
{
throw new UnsupportedOperationException("no such pizza");
}
return pizza;
}
}
abstract class Pizza
{
public void prepare()
{
System.out.println("pizza prepared");
}
public void bake()
{
System.out.println("pizza baked");
}
public void box()
{
System.out.println("pizza boxed");
}
}
class CheesePizza extends Pizza
{
@Override
public void prepare()
{
System.out.println("CheesePizza prepared");
}
}
class ClamPizza extends Pizza
{
@Override
public void prepare()
{
System.out.println("ClamPizza prepared");
}
}
以上情况只限于一家Store和一家factory,当全国各地有多家store和多家factory的时候,我们需要把静态函数改为非静态,以便继承等复用手段:
package javaapplication2;
public class Main
{
public static void main(String[] args)
{
PizzaStore store = new PizzaStore();
store.orderPizza("ClamPizza");
}
}
class PizzaStore
{
public Pizza orderPizza(String pizzaType)
{
PizzaFactory factory = new PizzaFactory();
Pizza pizza = factory.createPizza(pizzaType);
pizza.prepare();
pizza.bake();
pizza.box();
return pizza;
}
}
class PizzaFactory
{
public Pizza createPizza(String pizzaType)
{
Pizza pizza;
if (pizzaType.equals("CheesePizza"))
{
pizza = new CheesePizza();
}
else if (pizzaType.equals("ClamPizza"))
{
pizza = new ClamPizza();
}
else
{
throw new UnsupportedOperationException("no such pizza");
}
return pizza;
}
}
abstract class Pizza
{
public void prepare()
{
System.out.println("pizza prepared");
}
public void bake()
{
System.out.println("pizza baked");
}
public void box()
{
System.out.println("pizza boxed");
}
}
class CheesePizza extends Pizza
{
@Override
public void prepare()
{
System.out.println("CheesePizza prepared");
}
}
class ClamPizza extends Pizza
{
@Override
public void prepare()
{
System.out.println("ClamPizza prepared");
}
}
我们看到,每次PizzaStore开始orderPizza的时候,就要新建一个工厂。问题是,这个工厂并不确定:当某些PizzaStore需要想一个工厂要求生产披萨,而另外一些PizzaStore需要找另外一个工厂生产时,orderPizza这个函数就显得不稳定了。我们让PizzaStore到底对应什么factory由客户端决定,让服务器端保持稳定:
package javaapplication2;
public class Main
{
public static void main(String[] args)
{
PizzaFactory factory = new PizzaFactory(); //先造一个厂房,专门生产披萨
PizzaStore store = new PizzaStore(factory);//再造一个店面,专门销售披萨
store.orderPizza("ClamPizza"); //客户要什么披萨,由参数传递
}
}
class PizzaStore
{
PizzaFactory factory = null;
public PizzaStore(PizzaFactory factory)
{
this.factory = factory;
}
public Pizza orderPizza(String pizzaType)
{
Pizza pizza = factory.createPizza(pizzaType);
pizza.prepare();
pizza.bake();
pizza.box();
return pizza;
}
}
class PizzaFactory
{
public Pizza createPizza(String pizzaType)
{
Pizza pizza;
if (pizzaType.equals("CheesePizza"))
{
pizza = new CheesePizza();
}
else if (pizzaType.equals("ClamPizza"))
{
pizza = new ClamPizza();
}
else
{
throw new UnsupportedOperationException("no such pizza");
}
return pizza;
}
}
abstract class Pizza
{
public void prepare()
{
System.out.println("pizza prepared");
}
public void bake()
{
System.out.println("pizza baked");
}
public void box()
{
System.out.println("pizza boxed");
}
}
class CheesePizza extends Pizza
{
@Override
public void prepare()
{
System.out.println("CheesePizza prepared");
}
}
class ClamPizza extends Pizza
{
@Override
public void prepare()
{
System.out.println("ClamPizza prepared");
}
}
目前,该设计由以下几块组成:
(1) 由客户端Main根据客人要求,向服务器传递不同披萨的字符串,并决定由哪个工厂产生披萨,由哪个商店卖给披萨。
(2) 从制作到打包披萨的过程由PizzaStore类中的orderPizza方法来控制。
(3) 由于披萨有不同种类,为了让PizzaStore类中的内容保持稳定,我们设计一个专门的“工厂”PizzaFactory来负责完成orderPizza中的createPizza方法。披萨的参数(决定具体什么种类的披萨)由客户端递交给PizzaStore,再传递给PizzaFactory。