设计模式--工厂模式

总的说来,工厂模式有两种:工厂方法和抽象工厂。

工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化方法推迟到子类。利用工厂方法创建对象,通常需要继承一个类,并覆盖它的工厂方法。

举例如下(还是来自《Head First 设计模式》中的例子):

1.工厂方法

现在我们要买一个NY风味的Cheese Pizza,那么首先要得到一个生产NY风味的Pizza的工厂,然后点菜(传入需要的风味名称:”cheese“)

PizzaStore nyStore = new NYPizzaStore();
Pizza pizza1 = nyStore.orderPizza("cheese");

NYPizzaStore是生产NY风味Pizza的工厂,它继承自PizzaStore。提供了一个接口抽象方法
abstract Pizza creatPizza(String type)
根据传入的参数,生产相应类型的Pizza。

PizzaStore定义如下:

import edu.zju.www.Product.Pizza;;

public abstract class PizzaStore {
	protected abstract Pizza creatPizza(String type);             //这里提供了一个接口,让子类实现。从而到达了让子类去决定实例化类型的目的!
	public Pizza orderPizza(String type){
		Pizza pizza	;
		pizza = creatPizza(type);
		pizza.prepare();
		pizza.cut();
		pizza.box();
		return pizza;
	}
}

NYPizza覆盖了:

public Pizza creatPizza

其定义如下:

public class NYPizzaStore extends PizzaStore {

	@Override
	public Pizza creatPizza(String item) {          //这里是具体生产的方法,为了简单起见,只生产一种风味cheese
		// TODO Auto-generated method stub
		if(item.equals("cheese")){
			return new NYStyleCheesePizza();
		}else 
			return null; 
		}
	}

产品是Pizza。

Pizza的定义如下:

import java.util.ArrayList;

public abstract class Pizza {
	String name;
	String dough;
	String sauce;
	ArrayList topping = new ArrayList();
	public void prepare(){
		System.out.println("preparing " + name);
		System.out.println("Tossing dough...");
		System.out.println("Adding sauce...");
		System.out.println("Adding toppings:");
		for(int i = 0; i < topping.size();i++){
			System.out.println("  " + topping.get(i));
		}
	}
	public void bake(){
		System.out.println("baking at 350");
	}
	public void cut(){
		System.out.println("cutting the pizza into dialognal slices");
	}
	public void box(){
		System.out.println("Place the pizza into box");
	}
	public String getName(){
		return name;
	}
}
NY风格的CheesePizza继承自Pizza,定义如下:

public class NYStyleCheesePizza extends Pizza {
	public NYStyleCheesePizza(){
		name = "NY Syle Sauce and Cheese Pizza";
		dough = "Thin Crust Dough";
		sauce = "Marina Sauce";
		topping.add("Grated Regginao Cheese");
	}
}

运行结果:

preparing NY Syle Sauce and Cheese Pizza
Tossing dough...
Adding sauce...
Adding toppings:
  Grated Regginao Cheese
cutting the pizza into dialognal slices
Place the pizza into box


2.抽象工厂

通过抽象工厂所提供的接口,可以创建产品的家族而不要指定具体的类。(抽象工厂提供的接口,就是为子类搭好了框架,所以所有的子类看起来本质上都一样,只是表现形式不一样。

假设,生产Pizza需要3种原料:Dough, Sauce, Cheese。那么,就可以定义一个抽象工厂:PizzaIngredientFactoy

public interface PizzaIngredientFactoy {
	public Dough createDough();

	public Sauce createSauce();

	public Cheese createCheese();
}

而具体的生产NYPizzaIngredient的工厂NYPizzaIngredientFactoty集成了PizzaIngredientFactoy:

public class NYPizzaIngredientFactoty implements PizzaIngredientFactoy {

	@Override
	public Dough createDough() {
		// TODO Auto-generated method stub
		return new DoughNY();
	}

	@Override
	public Sauce createSauce() {
		// TODO Auto-generated method stub
		return new SauceNY();
	}

	@Override
	public Cheese createCheese() {
		// TODO Auto-generated method stub
		return new CheeseNY();
	}

}

当然,为了完善程序,自己还需要定义Dough, DoughNY, Sauce, SauceNY, Cheese, CheeseNY。(NY就是New york,代表new jork风味的Pizza)

这回Pizza的类定义如下:

public abstract class Pizza {
	Dough dough;
	Sauce sauce;
	Cheese cheese;
	public abstract void prepare();
}

具体类CheesePizza定义如下:

注意CheesePizza类使用了一个常用的手法:组合

public class CheesePizza extends Pizza {
	PizzaIngredientFactoy ingredientFactory;               //注意这里!!!!使用了组合

	public CheesePizza(PizzaIngredientFactoy ingredientFactory) {
		this.ingredientFactory = ingredientFactory;
	}

	@Override
	public void prepare() {
		// TODO Auto-generated method stub
		System.out.println("Preparing.... ");
		dough = ingredientFactory.createDough();
		sauce = ingredientFactory.createSauce();
		cheese = ingredientFactory.createCheese();
	}
}

最后,《Head First 设计模式》总结了两个方法的不同(有面试题目问到哦)

相同点:

工厂方法与抽象工厂都负责对象的创建,都是力图将类型的定义延迟到子类中(由子类来决定创建的类型)

不同点:

工厂方法使用继承,而抽象工厂使用组合:

可以看到,具体产品CheesePizza类中有一个Factory;

而在工厂方法中,要创建CheesePizza,首先要在外面自己创造一个Factory,然后调用工厂的创建方法并传入参数。


你可能感兴趣的:(设计模式--工厂模式)