HeadFirst設計模式(四) - 工廠模式之1 - 簡單工廠

爲何要使用工廠?

    當看到new時,就會想到具體這個詞。java

    是的,當使用new時,確實是在實例化一個具體累,因此用的確實是實現,而不是接口。針對接口編程,能夠隔離掉之後系統可能發生的一大堆改變。由於若是代碼是針對接口編寫的,那麼經過多態,可使用任何接口的實現類。編程

    除了使用new操做符以外,還有更多製造對象的方法。實例化這個活動不該該老是公開地進行。設計模式

使用一個披薩店的例子

假設有一個披薩店,須要一個披薩管理系統。ide

咱們決定使用面向對象的方式來實現這個系統,通過分析後,代碼可能會這麼寫:函數

/**
 * 這裏一個披薩店的實現類。
 * */
public class PizzaStore {
	
	/**
	 * 訂購披薩的方法,返回一個披薩餅對象。
	 * */
	public Pizza orderPizza() {
		// 建立一個披薩餅對象。
		Pizza pizza = new Pizza("披薩餅");
		return pizza;
	}
}

    作法是定義一個Pizza類,有一個name字段,重寫toString()方法。測試

    接着編寫一個PizzaStore類,該類有一個orderPizza()方法,用於訂購披薩。this

    最後編寫main函數進行測試。spa

須要更多的披薩類型

    通過一段時間後,披薩店有了更多種類的披薩餅,簡單的一個Pizza對象已經應付不來了。咱們須要更多的披薩對象,爲了讓系統有彈性,咱們把Pizza類定義爲抽象的,讓具體的披薩對象集成它。設計

/**
 * 披薩對象的抽象類,全部類型的披薩對象繼承自該類。
 * */
public abstract class Pizza {
	
	public Pizza() { }

	public Pizza(String name) {
		this.name = name;
	}
	
	/**
	 * 對披薩進行前期處理。
	 * 擀麪、加佐料等工藝。
	 * */
	public void prepare() {
		System.out.println(" ==> 對" + name + "進行前期處理...");
	}
	
	/**
	 * 烘培披薩。
	 * */
	public void bake() {
		System.out.println(" ==> 對" + name + "進行烘培處理...");
	}
	
	/**
	 * 切割披薩。
	 * */
	public void cut() {
		System.out.println(" ==> 對" + name + "進行切割處理...");
	}
	
	/**
	 * 包裝處理。
	 * */
	public void box() {
		System.out.println(" ==> 對" + name + "進行包裝處理...");
	}

	@Override
	public String toString() {
		return "披薩 [名稱=" + name + "]";
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	private String name;
}
/**
 * 芝士披薩對象,繼承自披薩抽象類。
 * */
public class CheesePizza extends Pizza { 
	public CheesePizza() {
		super.setName("芝士披薩");
	}
}

/**
 * 希臘披薩,繼承自披薩抽象類。
 * */
public class GreekPizza extends Pizza { 
	public GreekPizza() {
		super.setName("希臘披薩");
	}
}


/**
 * 意大利香腸披薩,繼承自披薩抽象類。
 * */
public class PepperoniPizza extends Pizza { 
	public PepperoniPizza() {
		super.setName("意大利香腸披薩");
	}
}

    咱們有了具體的披薩類型,接着重寫orderPizza方法,經過類型來決定建立具體的披薩:code

/**
 * 這裏一個披薩店的實現類。
 * */
public class PizzaStore {
	
	/**
	 * 訂購披薩的方法,返回一個披薩餅對象。
	 * */
	public Pizza orderPizza(String type) {
		Pizza pizza;
		// 經過類型來肯定返回哪一種披薩。
		if("cheese".equals(type)) {
			pizza = new CheesePizza();
		} else if ("greek".equals(type)) {
			pizza = new GreekPizza();
		} else if ("pepperoni".equals(type)) {
			pizza = new PepperoniPizza();
		} else {
			return null;
		}
		
		// 擀麪上料、烘培、切片、裝盒。
		pizza.prepare();
		pizza.bake();
		pizza.cut();
		pizza.box();
		
		return pizza;
	}
}

     進行測試:

    經過披薩類型訂購了兩種不一樣的披薩,很是方便,可是……

壓力來自於增長更多的披薩類型

    通過了一段時間,有出現了披薩新種類,好比海鮮蛤哩披薩和素食披薩等等,披薩店也學會了這些披薩的作法並要把它們加入到系統中。同時,希臘風味披薩賣得不太好,要將它從系統中移除。

    很明顯,若是實例化「某些」具體類,每次都要去修改PizzaStore類源碼,由於要修改orderPizza()方法中的語句。

    還有一點,這段建立披薩的代碼放在了PizzaStore中的ordarPizza () 方法,與pizza的處理方法寫到了一塊兒。若是有一天披薩店的菜單對象也須要建立披薩,則須要拷貝orderPizza()方法中建立披薩的那段if-else代碼到菜單對象。修改時就要修改兩處,若是有20個地方用到了建立披薩的這段代碼呢?

    是時候將建立披薩的代碼封裝起來了!

    咱們須要將if-else的代碼搬到另外一個對象中,這個新對象只管如何建立披薩。若是任何對象想要建立披薩,找它就對了。咱們稱這個新對象爲「工廠」(factory)。建立這個工廠,並修改現有代碼:

    首先修改PizzaStore類中的orderPizza()方法,將new披薩的那段if-else代碼從方法中移除:

    接下來建立新對象,披薩工廠:

/**
 * SimplePizzaFactory是披薩的工廠類,它只作一件事,就是建立披薩。
 */
public class SimplePizzaFactory {
	
	/**
	 * 經過類型來肯定返回哪一種披薩。
	 * */
	public static Pizza createPizza(String type) {
		Pizza pizza;
		// 經過類型來肯定返回哪一種披薩。
		if ("cheese".equals(type)) {
			pizza = new CheesePizza();
		} else if ("pepperoni".equals(type)) {
			pizza = new PepperoniPizza();
		} else if ("clam".equals(type)) {
			pizza = new ClamPizza();
		} else if ("veggie".equals(type)) {
			pizza = new VeggiePizza();
		} else {
			return null;
		}
		return pizza;
	}
}

    最後,在PizzaStore類的orderPizza()方法中,經過工廠來建立披薩:

/**
 * 這裏一個披薩店的實現類。
 * */
public class PizzaStore {
	
	/**
	 * 訂購披薩的方法,返回一個披薩餅對象。
	 * */
	public Pizza orderPizza(String type) {
		// 經過披薩工廠建立披薩。
		Pizza pizza = SimplePizzaFactory.createPizza(type);
		
		// 擀麪上料、烘培、切片、裝盒。
		pizza.prepare();
		pizza.bake();
		pizza.cut();
		pizza.box();
		
		return pizza;
	}
}

    測試結果以下:


定義簡單工廠

    簡單工廠其實不是一個設計模式,反而比較像是一種編程習慣。但因爲常常被使用,因此也概括到了工廠方法中。不要由於簡單工廠不是一個「真正的」模式,就忽略了它的用法。讓咱們來看看如今披薩管理系統的類圖:

    PizzaStore是工廠的「客戶」。PizzaStore如今經過SimplePizzaFactory取得披薩實例。

    SimplePiazzaFactory是工廠方法,用來建立披薩。

    Pizza是「產品」的抽象類,每一個具體產品必須拓展抽象的Pizza類,並設計稱一個具體類。這樣一來,就能夠被工廠建立,並返回給客戶。

    到這裏簡單工廠的介紹就差很少了,多謝它爲咱們暖身。接下來登場的是兩個重量級的模式,它們都是工廠。

相關文章
相關標籤/搜索