Java設計模式學習筆記——工廠模式與抽象工廠模式

智慧包 發表於 2020-10-16

首先來看看工廠模式的概念

定義了一個建立物件的介面,由子類決定要例項化的類是哪一個,工廠方法讓類把例項化推遲到子類

(例子參考自《HeadFirst設計模式》)

假設有一家披薩店,售賣多種不同的披薩,而且可以有多個加盟店,應該如何實現?

首先我們把披薩類做出來

public class Pizza {
	
	String name;
	String sauce;
	ArrayList toppings = new ArrayList();
	
	public void prepare() {
		System.out.println("準備開始做 " + name);
		System.out.println("新增調料...");
		System.out.print("新增配料:");
		for(int i = 0; i < toppings.size(); i++) {
			System.out.println(" " + toppings.get(i));
		}
	}
	
	public void bake() {
		System.out.println("放入烤箱烘烤");
	}
	
	public void cut() {
		System.out.println("切成小塊");
	}
	
	public void box() {
		System.out.println("放入披薩盒中");
	}
	
	public String getName() {
		return name;
	}
}

還需要一個披薩店

public abstract class PizzaStore {
	
	public Pizza orderPizza(String type) {
		Pizza pizza;
		pizza = createPizza(type);
		pizza.prepare();
		pizza.bake();
		pizza.cut();
		pizza.box();
		return pizza;
	}
	
	public abstract Pizza createPizza(String type);
	
}

接下來建立一個店鋪(總店),後續還可以有更多的加盟店,只需要繼承PizzaStore這個抽象類就可以了

public class APizzaStore extends PizzaStore{

	@Override
	public Pizza createPizza(String type) {
		if(type.equals("cheese")){
			return new ACheesePizza();
		}else if(type.equals("ham")) {
			return new AHamPizza();
		}else {
			return null;
		}
	}
	
}

往這個店鋪中新增幾款披薩

public class AHamPizza extends Pizza{
	
	public AHamPizza() {
		name = "火腿披薩";
		sauce = "沙拉醬";
		toppings.add("優質火腿");
	}

}
public class ACheesePizza extends Pizza{
	
	public ACheesePizza() {
		name = "乳酪披薩";
		sauce = "番茄醬";
		toppings.add("優質乳酪");
	}
	
}

至此,我們就可以通過我們建立的披薩店來點餐了

public class PizzaTest {

	public static void main(String[] args) {
		//選擇A店鋪點餐
		PizzaStore pizzaStore = new APizzaStore();
		//選擇乳酪披薩
		Pizza cheesePizza = pizzaStore.createPizza("cheese");
		//開始製作披薩
		cheesePizza.prepare();
		System.out.println("點了一個" + cheesePizza.getName());
		Pizza hamPizza = pizzaStore.createPizza("ham");
		hamPizza.prepare();
		System.out.println("再來一個" + hamPizza.getName());
	}

}

執行結果如下
在這裡插入圖片描述
現在又多了一個新的需求,我們要確保每一家披薩店的原料是一致的,所以我們需要建立原料家族,這裡我們就需要用到抽象工廠模式了

什麼是抽象工廠模式?

抽象工廠模式提供一個介面,用於建立相關或依賴物件的家族,而不需要明確指定具體類

先建立一個原料工廠

public interface PizzaIngredientFactory {
	
	public Sauce createSauce();
	public Cheese createCheese();
	
}

A店的原料工廠,後續可以把加盟店的原料工廠都加進來,按照需求返回不同的原料就行了

public class APizzaIngredientFactory implements PizzaIngredientFactory{

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

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

披薩類

public abstract class Pizza {
	
	String name;
	Sauce sauce;
	Cheese cheese;
	
	public abstract void prepare();
	
	public void bake() {
		System.out.println("放入烤箱烘烤");
	}
	
	public void cut() {
		System.out.println("切成小塊");
	}
	
	public void box() {
		System.out.println("放入披薩盒中");
	}
	
	public String getName() {
		return name;
	}
	
	public void setName(String name) {
		this.name = name;
	}
}

A店的乳酪披薩

public class ACheese implements Cheese{
	public ACheese() {
		System.out.println("用到了ACheese乳酪");
	}
}

A店的甜醬披薩

public class ASauce implements Sauce{
	public ASauce() {
		System.out.println("用了ASauce調料");
	}
}

還得稍微修改一下A披薩店

public class APizzaStore extends PizzaStore{

	@Override
	public Pizza createPizza(String type) {
		// TODO Auto-generated method stub
		Pizza pizza = null;
		PizzaIngredientFactory ingredientFactory = new APizzaIngredientFactory();
		if(type.equals("cheese")) {
			pizza = new CheesePizza(ingredientFactory);
			pizza.setName("乳酪披薩");
		}else if(type.equals("sauce")) {
			pizza = new SaucePizza(ingredientFactory);
			pizza.setName("甜醬披薩");
		}
		return pizza;
	}

}

具體的原材料像乳酪,火腿這些需要自己分別宣告一個介面,各種不同品種的乳酪和火腿實現對應的介面來滿足不同的風味就行了,這裡程式碼就不展示了

最後來測試一下

public class PizzaTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		PizzaStore aPizzaStore = new APizzaStore();
		Pizza pizza = aPizzaStore.orderPizza("cheese");
	}

}

在這裡插入圖片描述