簡單工廠不是設計模式。它只是將物件創建與客戶端程式碼解耦。換句話說,簡單工廠透過將實例化邏輯移至單獨的類別來封裝物件實例化。
簡單工廠常與工廠模式混淆。我們將研究簡單工廠來闡明它們的差異。另外,學習簡單工廠可以幫助我們輕鬆理解工廠模式。
應避免對具體實作進行編程,因為這會使應用程式非常難以維護。對介面進行程式設計總是更好的選擇。如果您在客戶端程式碼中實例化一個具體類,那麼簡單工廠會派上用場,因為簡單工廠可以將物件建立與客戶端分離。這使得我們的應用程式更具可擴展性和可維護性。
我們正在為漢堡店開發系統。系統需要製作牛肉漢堡、雞肉漢堡等各種漢堡。
我們的第一次嘗試是這樣的:
// Client orders a burger Burger orderBurger(String type) { Burger burger; if (type.equals("beef")) { burger = new BeefBurger(); } else if (type.equals("chicken")) { burger = new ChickenBurger(); } else if (type.equals("fish")) { burger = new FishBurger(); } burger.prepareBun(); burger.grillPatty(); burger.addToppings(); burger.wrap(); return burger; }
問題是,我們正在針對實作進行編碼,而不是針對介面進行編碼。在哪裡?我們使用 if 語句並根據漢堡類型實例化一個特定類別。
為什麼會出現這個問題呢?我們的客戶端程式碼與物件創建緊密耦合,導致靈活性降低!假設我們不再銷售魚漢堡,並開始銷售素食漢堡。我們需要存取我們的客戶端程式碼並修改它。也就是說不關閉修改。
為了解決這個問題,我們可以創建單獨的類,它只負責物件的創建。那麼我們的客戶端程式碼就不需要擔心物件創建並且能夠依賴抽象。這種技術稱為「封裝變化的內容」。我們預計有關實例化具體物件的程式碼將經常更改,而未來所有漢堡中的prepareBun()、grillPatty()、addToppings()、wrap()過程可能會保持不變。
簡單工廠的優點是可以被其他類別重複使用。我們可能有其他客戶端類別,例如 BurgerRestaurant、BurgerCateringShop,它們將使用 SimpleBurgerFactory.createBurger() 方法。
客戶
客戶端透過SimpleBurgerFactory實例化特定的漢堡物件。請注意,從客戶端角度來看,我們不知道將創建哪個特定漢堡,也就是說,物件創建邏輯現在與客戶端解耦。
簡單漢堡工廠
這個類別封裝了不同的內容,在本例中是物件創建邏輯! createBurger() 被宣告為靜態方法,因為客戶端想要使用此類來實例化物件(當然,在實例化它之前我們不能有實例!)。 createBurger() 接受 BurgerType 枚舉來決定應創建哪種類型的漢堡。
漢堡
這個抽象類別提供所有漢堡之間的通用介面並定義預設行為。
漢堡子類
這是我們的具體產品。只要擴展 Burger 類,他們就可以透過重寫方法來實現特定行為。
// Client orders a burger Burger orderBurger(String type) { Burger burger; if (type.equals("beef")) { burger = new BeefBurger(); } else if (type.equals("chicken")) { burger = new ChickenBurger(); } else if (type.equals("fish")) { burger = new FishBurger(); } burger.prepareBun(); burger.grillPatty(); burger.addToppings(); burger.wrap(); return burger; }
public enum BurgerType { BEEF, CHICKEN, FISH, VEGGIE }
// Abstract Product public abstract class Burger { public BurgerType burgerType; public List<String> toppings = new ArrayList<>(); public void prepareBun() { System.out.println("Preparing a bun"); } public void grillPatty() { if (burgerType == null) { throw new IllegalStateException("pattyType is undefined"); } System.out.println("Grill a " + burgerType + " patty"); } public void addToppings() { for (String item : toppings) { System.out.println("Add " + item); } } public void wrap() { System.out.println("Wrap a burger up"); } }
// Concrete product public class BeefBurger extends Burger { public BeefBurger() { burgerType = BurgerType.BEEF; List<String> items = List.of("lettuce", "pickle slices", "tomato slice", "BBQ sauce"); toppings.addAll(items); } }
// Concrete product public class VeggieBurger extends Burger { public VeggieBurger() { burgerType = BurgerType.VEGGIE; List<String> items = List.of("smoked paprika", "garlic chips", "crushed walnuts", "veggie sauce"); toppings.addAll(items); } // Concrete product can implement specific behavior that differs from other products @Override public void wrap() { System.out.println("Wrapping paper shouldn't print any meats but vegetables"); } }
// Simple factory, responsible for instantiating an object public class SimpleBurgerFactory { public static Burger createBurger(BurgerType type) { return switch (type) { case BEEF -> new BeefBurger(); case CHICKEN -> new ChickenBurger(); case FISH -> new FishBurger(); case VEGGIE -> new VeggieBurger(); default -> throw new IllegalArgumentException("unknown burger type"); }; } }
輸出:
public class Client { public static void main(String[] args) { Burger burger = orderBurger(BurgerType.VEGGIE); System.out.println(burger); // Check if the object is actually veggie burger } public static Burger orderBurger(BurgerType type) { // Factory is responsible for object creation Burger burger = SimpleBurgerFactory.createBurger(type); burger.prepareBun(); burger.grillPatty(); burger.addToppings(); burger.wrap(); return burger; } }
您可以在這裡查看所有設計模式的實作。
GitHub 儲存庫
附註
我是剛開始寫科技博客,如果您對我的寫作有什麼建議,或者有任何困惑的地方,請留言!
感謝您的閱讀:)
以上是簡單工廠的詳細內容。更多資訊請關注PHP中文網其他相關文章!