首页 > 代码库 > 《Head First 设计模式》学习笔记——工厂模式 + 抽象工厂模式

《Head First 设计模式》学习笔记——工厂模式 + 抽象工厂模式

设计模式
工厂模式:定义一个创建对象的接口,但由子类决定要实例化的是哪一个。工厂方法让类把实例化推迟到子类。
所谓的“决定”,并不是指模式允许子类本身在运行时做决定,而是指在编写创建者类时,不需要知道实际创建的产品是哪一个。选择了使用这个子类,就自然的决定了实际创建的产品是什么。

抽象工厂模式:提供一个接口,用于创建相关或依赖对象的家族,而不需要指定具体类。
抽象工厂的任务时定义一个负责创建一组产品的接口。这个接口内的每个产品都负责创建一个具体产品,使用工厂方法。


设计原则
(1)多用组合,少用继承
(2)针对接口编程,不针对实现编程
(3)为交互对象之间的松耦合设计而努力
(4)类应该对扩展开放,对修改关闭
(5)依赖倒用原则:要依赖抽象,不要依赖具体类。
不能让高层组件依赖底层组件,而且,不管是高层或低层,两者都应该依赖于抽象。
指导方针:
变量不可以持有具体类的引用(如果使用new,可以改用工厂来避开这样做法);
不要让类派生自具体类(派生自一个接口或者抽象类);
不要覆盖基类中已实现的方法(积累中已经实现的方法,应该有所有子类共享)

要点
所有的工厂都是用来封装对象的创建的。
工厂方法使用继承:把对象的创建委托给子类,子类实现工厂方法来创建对象,
抽象工厂使用对象组合:对象的创建被实现在工厂接口所暴露的方法中。
工厂方法允许将实例化延迟到子类进行。

public abstract class Pizza {
	String name;
	String dough;
	String sauce;
	ArrayList toppings = new ArrayList();
 
	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 < toppings.size(); i++) {
			System.out.println("   " + toppings.get(i));
		}
	}
  
	void bake() {
		System.out.println("Bake for 25 minutes at 350");
	}
 
	void cut() {
		System.out.println("Cutting the pizza into diagonal slices");
	}
  
	void box() {
		System.out.println("Place pizza in official PizzaStore box");
	}
 
	public String getName() {
		return name;
	}

	public String toString() {
		StringBuffer display = new StringBuffer();
		display.append("---- " + name + " ----\n");
		display.append(dough + "\n");
		display.append(sauce + "\n");
		for (int i = 0; i < toppings.size(); i++) {
			display.append((String )toppings.get(i) + "\n");
		}
		return display.toString();
	}
}

public class NYStyleCheesePizza extends Pizza {

	public NYStyleCheesePizza() { 
		name = "NY Style Sauce and Cheese Pizza";
		dough = "Thin Crust Dough";
		sauce = "Marinara Sauce";
 
		toppings.add("Grated Reggiano Cheese");
	}
}

public abstract class PizzaStore {
 
	abstract Pizza createPizza(String item);
 
	public Pizza orderPizza(String type) {
		//创建对象的接口
		Pizza pizza = createPizza(type);
		System.out.println("--- Making a " + pizza.getName() + " ---");
		pizza.prepare();
		pizza.bake();
		pizza.cut();
		pizza.box();
		return pizza;
	}
}

public class NYPizzaStore extends PizzaStore {
	//由子类来决定具体实例化哪个
	Pizza createPizza(String item) {
		if (item.equals("cheese")) {
			return new NYStyleCheesePizza();
		} else if (item.equals("veggie")) {
			return new NYStyleVeggiePizza();
		} else if (item.equals("clam")) {
			return new NYStyleClamPizza();
		} else if (item.equals("pepperoni")) {
			return new NYStylePepperoniPizza();
		} else return null;
	}
}


public class PizzaTestDrive {
 
	public static void main(String[] args) {
		PizzaStore nyStore = new NYPizzaStore();
		PizzaStore chicagoStore = new ChicagoPizzaStore();
 
		Pizza pizza = nyStore.orderPizza("cheese");
		System.out.println("Ethan ordered a " + pizza.getName() + "\n");
 
		pizza = chicagoStore.orderPizza("cheese");
		System.out.println("Joel ordered a " + pizza.getName() + "\n");
}