设计模式:工厂方法模式

简介

工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法模式让实例化推迟到子类。

代码

pizza抽象类

public abstract class Pizza {
	protected String name; // 名称
	protected String dough; // 面团
	protected String sause; // 酱料
	protected List<String> toppings = new ArrayList<String>(); // 佐料
	/**
	 * 准备
	 */
	public void prepare() {
		System.out.println("Preparing " + name);
		System.out.println("Tossing dough");
		System.out.println("Adding sause");
		System.out.println("Adding toppings");
		for (int i = 0; i < toppings.size(); i++) {
			System.out.println("   " + toppings.get(i));
		}
	}
	/**
	 * 烘烤
	 */
	public void bake() {
		System.out.println("Bake for 25 minutes at 350");
	}
	/**
	 * 切割
	 */
	public void cut() {
		System.out.println("Cutting the pizza into diagonal slices");
	}
	/**
	 * 装盒
	 */
	public void box() {
		System.out.println("Place pizza in official PizzaStore box");
	}

	public String getName() {
		return name;
	}
}

pizza实现类

芝加哥风味

public class ChicagoStyleCheesePizza extends Pizza {
	public ChicagoStyleCheesePizza() {
		name = "Chicago Style Deep Dish "+this.getClass().getSimpleName()+" Pizza";
		dough = "Extra Thick Crust Dough";
		sause = "Plum Tomato Sauce";

		toppings.add("Shredded Mozzarella Cheese");
	}

	public void cut() {
		System.out.println("Cutting the Pizza into square slices");
	}
}

纽约风味

public class NYStyleCheesePizza extends Pizza {
	public NYStyleCheesePizza() {
		name = "Ny Style Sauce and "+this.getClass().getSimpleName()+" Pizza";
		dough = "Thin Crust Dough";
		sause = "Marinara Sauce";

		toppings.add("Crated Reggiano Cheese");
	}
 }

商店抽象类

public abstract class PizzaStore {
	 public Pizza orderPizza(String type){
		Pizza pizza;
		pizza = createPizza(type);

		pizza.prepare();
		pizza.bake();
		pizza.cut();
		pizza.box();

		return pizza;
	}

	/*
	 * 创建pizza的方法交给子类去实现
	 */
    abstract Pizza createPizza(String type);
}

商店实现类

纽约商店

/**
 * 纽约披萨商店
 * @author Mr.Li
 *
 */
public class NYPizzaStore extends PizzaStore{
	@Override
	Pizza createPizza(String item) {
		Pizza pizza = null;
		if ("cheese".equals(item)) {
			pizza = new NYStyleCheesePizza();
		} else if ("veggie".equals(item)) {
			pizza = new NYStyleVeggiePizza();
		} 
		return pizza;
	}
}

芝加哥商店

/**
 * 芝加哥披萨商店
 * @author Mr.Li
 *
 */
public class ChicagoPizzaStore extends PizzaStore {
	Pizza createPizza(String type) {
		Pizza pizza = null;
		if ("cheese".equals(type)) {
			pizza = new ChicagoStyleCheesePizza();
		} else if ("clam".equals(type)) {
			pizza = new ChicagoStyleClamPizza();
		}
		return pizza;
	}
}

客户调用

	public static void main(String[] args) {
		System.out.println("---------Joel 需要的芝加哥的深盘披萨---------");
		ChicagoPizzaStore chicagoPizzaStore = new ChicagoPizzaStore(); // 建立芝加哥的披萨店
		Pizza joelPizza = chicagoPizzaStore.orderPizza("cheese"); // 下订单
		System.out.println("Joel ordered a " + joelPizza.getName() + "\n");

		System.out.println("---------Ethan 需要的纽约风味的披萨---------");
		NYPizzaStore nyPizzaStore = new NYPizzaStore();
		Pizza ethanPizza = nyPizzaStore.orderPizza("cheese");
		System.out.println("Ethan ordered a " + ethanPizza.getName() + "\n");
	}

visio图

优缺点及使用场景

/**
	 * 优点:	1、  在工厂方法中,用户只需要知道所要产品的具体工厂,无须关系具体的创建过程,甚至不需要具体产品类的类名。
	 * 		2、  在系统增加新的产品时,我们只需要添加一个具体产品类和对应的实现工厂,无需对原工厂进行任何修改,很好地符合了“开闭原则”。
	 * 缺点:	1、  每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。
	 * 使用场景:	1、一个类不知道它所需要的对象的类。在工厂方法模式中,我们不需要具体产品的类名,我们只需要知道创建它的具体工厂即可。
	 * 			2、一个类通过其子类来指定创建那个对象。在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,在程序运行时,子类对象将覆盖父类对象,从而使得系统更容易扩展。
	 * 			3、将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定。

	 */