跟著ChatGPT學習設計模式 - 工廠模式

程序员博博發表於2024-07-23

1. 前言

在工作過程中,越發覺得設計模式的重要性。經常會有人說工作5年的人,大學生隨便培訓1-2月也能做同樣的工作,沒錯,大學生的確可以做。

但其寫的程式碼,可維護性、可擴充套件性、新增新功能時方便還是簡單。甚至是軟實力的表現,如何溝通、如何推進專案進展、如何做專案排期,其實都是應屆生所不具備的。(當然工作5年的人和大學生沒不一樣的,那你就應該被社會所淘汰,不裁你,裁誰呢)

大家不需要趾高氣昂,但也不必要妄自菲薄。

針對此,我出了 《跟著ChatGPT學習設計模式》系列,歡迎大家點贊收藏轉發,今天我們學習工廠模式。包括:簡單工廠模式、工廠模式、抽象工廠模式

2. 簡單工廠模式

Q: 請你詳細解釋一下 簡單設計工廠模式,回答要簡潔,讓小朋友也能聽懂那種

什麼是簡單工廠模式?

簡單工廠模式是一種設計模式,它透過一個專門的類來負責建立其他類的例項。這個專門的類通常被稱為“工廠類”。簡單工廠模式的主要目的是將物件的建立過程封裝起來,使得客戶端程式碼不需要知道具體的建立細節。

為什麼需要簡單工廠模式?

  1. 簡化物件建立:客戶端程式碼不需要知道如何建立物件,只需要知道如何使用它們。
  2. 提高程式碼可維護性:如果需要更改物件的建立方式,只需要修改工廠類,而不需要修改客戶端程式碼。
  3. 減少重複程式碼:將物件建立的邏輯集中在一個地方,避免在多個地方重複相同的建立程式碼。

舉個生活中的例子

想象一下,你有一個玩具店,這個玩具店可以生產不同種類的玩具,比如小汽車、洋娃娃和積木。你只需要告訴店員你想要哪種玩具,店員就會幫你拿出來。

  • 店員:相當於工廠類。
  • 玩具:相當於需要建立的物件。
  • 你告訴店員你想要的玩具型別:相當於客戶端程式碼請求工廠類建立物件。

具體步驟

  1. 定義產品:首先,你需要定義各種玩具,比如小汽車、洋娃娃和積木。
  2. 建立工廠類:然後,你需要建立一個工廠類,這個類有一個方法可以根據你提供的玩具型別來建立相應的玩具。
  3. 使用工廠類:最後,你在需要玩具的時候,只需要呼叫工廠類的方法,告訴它你想要哪種玩具,它就會返回相應的玩具給你。

優點

  1. 簡化客戶端程式碼:客戶端程式碼不需要知道如何建立物件,只需要知道如何使用它們。
  2. 集中管理物件建立:將物件建立的邏輯集中在一個地方,便於管理和維護。
  3. 靈活性高:可以很容易地新增新的玩具型別,只需要修改工廠類,而不需要修改客戶端程式碼。

缺點

  1. 單一職責原則:工廠類可能會變得複雜,因為它需要處理所有物件的建立邏輯。
  2. 不支援擴充套件:如果需要新增新的玩具型別,必須修改工廠類的程式碼,這違反了開閉原則(對擴充套件開放,對修改關閉)。

總結

簡單工廠模式就像一個玩具店的店員,你告訴他你想要什麼玩具,他就會幫你拿出來。這樣你就不需要自己去找這些玩具了,只需要專注於玩就好了。

希望這個解釋對你有幫助!如果還有其他問題,儘管問吧。

Q: 那麼請用程式碼實現以下

public interface Animal {  
    void speak();  
}

public class Cat implements Animal {
    @Override
    public void speak() {
        System.out.println("Cat speak!");
    }
}

public class Dog implements Animal {
    @Override
    public void speak() {
        System.out.println("Dog speak!");
    }
}
public class AnimalFactory {
    // 在實際開發中可以使用ApplicationContext 配合@PostConstruct,來獲取Animal的所有實現類
    private static Map<String, Animal> map = new HashMap<>();

    static {
        map.put("dog", new Dog());
        map.put("cat", new Cat());
    }

    public static Animal createAnimal(String type) {
        if (map.containsKey(type)) {
            return map.get(type);
        }
        throw new IllegalArgumentException("Unknown animal type");
    }

}

public class Main {
    public static void main(String[] args) {

        // 一般建立dog還是cat,一般可以用type來判斷,每個類都有一個type
        // 或者根據配置,環境變數讀取等等都可以
        Animal dog = AnimalFactory.createAnimal("dog");
        dog.speak();

        Animal cat = AnimalFactory.createAnimal("cat");
        cat.speak();
    }
}

簡單工廠模式就是隻有一個factory,根據產品的type來建立不同型別的產品,適用於建立簡單的產品。這有是我們在程式碼中非常常用的一種策略模式,尤其是配合spring來使用,可以達到意想不到的效果。

3. 工廠模式

Q: 那工廠模式呢,請給出詳細的解釋

什麼是工廠模式?

工廠模式是一種建立型設計模式,它定義了一個建立物件的介面,但由子類決定要例項化的類是哪一個。工廠方法讓類的例項化推遲到子類。

為什麼需要工廠模式?

  1. 解耦:將物件的建立和使用分離,客戶端程式碼不需要知道具體的建立細節。
  2. 擴充套件性:可以透過新增新的子類來擴充套件產品種類,而不需要修改現有程式碼。
  3. 單一職責原則:每個工廠類只負責建立一種產品,職責單一,程式碼更清晰。

舉個生活中的例子

想象一下,你有一個玩具店,這個玩具店有不同的部門,每個部門負責生產一種特定的玩具,比如小汽車部門、洋娃娃部門和積木部門。你只需要找到相應的部門,他們就會幫你生產出你想要的玩具。

  • 玩具店:相當於工廠介面。
  • 不同的部門:相當於具體的工廠類。
  • 玩具:相當於需要建立的物件。
  • 你找到相應的部門:相當於客戶端程式碼請求具體的工廠類建立物件。

具體步驟

  1. 定義產品介面:首先,你需要定義一個玩具介面,所有的玩具都要實現這個介面。
  2. 建立具體產品類:然後,你需要建立具體的玩具類,比如小汽車、洋娃娃和積木,這些類都實現了玩具介面。
  3. 定義工廠介面:接下來,你需要定義一個工廠介面,這個介面有一個方法用來建立玩具。
  4. 建立具體工廠類:然後,你需要建立具體的工廠類,每個工廠類負責建立一種特定的玩具。
  5. 使用工廠類:最後,你在需要玩具的時候,只需要呼叫相應的工廠類的方法,它就會返回相應的玩具給你。

優點

  1. 解耦:客戶端程式碼不需要知道具體的建立細節,只需要知道工廠介面。
  2. 擴充套件性:可以透過新增新的具體工廠類來擴充套件產品種類,而不需要修改現有程式碼。
  3. 單一職責原則:每個工廠類只負責建立一種產品,職責單一,程式碼更清晰。

缺點

  1. 類的數量增加:每增加一種產品,就需要增加一個具體的工廠類,類的數量會增加。
  2. 複雜性增加:相比簡單工廠模式,工廠模式的結構更復雜,需要定義更多的介面和類。

總結

工廠模式就像一個玩具店的不同部門,每個部門負責生產一種特定的玩具。你只需要找到相應的部門,他們就會幫你生產出你想要的玩具。這樣你就不需要自己去建立這些玩具了,只需要專注於使用它們。

希望這個解釋對你有幫助!如果還有其他問題,儘管問吧。

Q: 那麼請用程式碼實現以下

public interface AnimalFactory {
    Animal createAnimal();
}

public class CatFactory implements AnimalFactory {
    @Override
    public Animal createAnimal() {
        return new Cat();
    }
}

public class DogFactory implements AnimalFactory {
    @Override
    public Animal createAnimal() {
        return new Dog();
    }
}
public class Main {
    public static void main(String[] args) {

        AnimalFactory dogFactory = getFactory("dog");
        Animal dog = dogFactory.createAnimal();
        dog.speak();

        AnimalFactory catFactory = getFactory("cat");
        Animal cat = catFactory.createAnimal();
        cat.speak();

    }

    // 一般建立dogFactory還是catFactory,一般可以用type來判斷,每個類都有一個type
    // 或者根絕配置,環境變數讀取等等都可以
    public static AnimalFactory getFactory(String animalType) {
        if ("dog".equals(animalType)) {
            return new DogFactory();
        } else if ("cat".equals(animalType)) {
            return new CatFactory();
        }
        throw new IllegalArgumentException("Unknown animal type");
    }
}

工廠模式相比於簡單工廠模式,它擁有一個AnimalFactory介面,具體每一個產品都有一個工廠。可以生成很複雜的產品,但隨之而來的也是膨脹的factory

4. 抽象工廠模式

Q: 那抽象工廠模式呢,請給出詳細的解釋

什麼是抽象工廠模式?

抽象工廠模式是一種建立型設計模式,它提供一個介面,用於建立一系列相關或相互依賴的物件,而無需指定它們具體的類。抽象工廠模式透過組合多個工廠方法來實現更復雜的物件建立。

為什麼需要抽象工廠模式?

  1. 產品族的概念:當系統需要處理多個產品族時,抽象工廠模式可以提供一個統一的介面來建立這些產品。
  2. 解耦:客戶端程式碼不需要知道具體的產品類,只需要知道工廠介面。
  3. 一致性:確保同一個產品族中的物件一起使用時是相容的。

舉個生活中的例子

想象一下,你有一個傢俱店,這個傢俱店可以生產不同風格的傢俱,比如現代風格和古典風格。每種風格的傢俱包括椅子和桌子。你只需要告訴店員你想要哪種風格的傢俱,店員就會幫你生產出相應風格的椅子和桌子。

  • 傢俱店:相當於抽象工廠介面。
  • 不同風格的傢俱部門:相當於具體的工廠類。
  • 椅子和桌子:相當於需要建立的物件。
  • 你告訴店員你想要的傢俱風格:相當於客戶端程式碼請求具體的工廠類建立物件。

具體步驟

  1. 定義產品介面:首先,你需要定義椅子和桌子的介面,所有的椅子和桌子都要實現這些介面。
  2. 建立具體產品類:然後,你需要建立具體的椅子和桌子類,比如現代風格的椅子和桌子,古典風格的椅子和桌子,這些類都實現了相應的介面。
  3. 定義抽象工廠介面:接下來,你需要定義一個抽象工廠介面,這個介面有方法用來建立椅子和桌子。
  4. 建立具體工廠類:然後,你需要建立具體的工廠類,每個工廠類負責建立一種特定風格的椅子和桌子。
  5. 使用工廠類:最後,你在需要傢俱的時候,只需要呼叫相應的工廠類的方法,它就會返回相應風格的椅子和桌子給你。

優點

  1. 產品族的建立:可以方便地建立一系列相關或相互依賴的物件。
  2. 解耦:客戶端程式碼不需要知道具體的產品類,只需要知道工廠介面。
  3. 一致性:確保同一個產品族中的物件一起使用時是相容的。

缺點

  1. 複雜性增加:相比工廠方法模式,抽象工廠模式的結構更復雜,需要定義更多的介面和類。
  2. 擴充套件困難:如果需要新增新的產品族,需要修改抽象工廠介面及其所有的具體工廠類。

總結

抽象工廠模式就像一個傢俱店的不同風格部門,每個部門負責生產一種特定風格的傢俱。你只需要告訴店員你想要哪種風格的傢俱,他們就會幫你生產出相應風格的椅子和桌子。這樣你就不需要自己去建立這些傢俱了,只需要專注於使用它們。

希望這個解釋對你有幫助!如果還有其他問題,儘管問吧。

Q: 那麼請用程式碼實現以下

我們現在不僅有動物,還有食物

public interface AnimalFood {
    void eat();
}

public class CatFood implements AnimalFood {
    @Override
    public void eat() {
        System.out.println("Cat is eating cat food.");
    }
}

public class DogFood implements AnimalFood {
    @Override
    public void eat() {
        System.out.println("Dog is eating dog food.");
    }
}
public interface AnimalFactory {
    Animal createAnimal();
    AnimalFood createAnimalFood();
}

public class CatFactory implements AnimalFactory {
    @Override
    public Animal createAnimal() {
        return new Cat();
    }

    @Override
    public AnimalFood createAnimalFood() {
        return new CatFood();
    }
}

public class DogFactory implements AnimalFactory {
    @Override
    public Animal createAnimal() {
        return new Dog();
    }

    @Override
    public AnimalFood createAnimalFood() {
        return new DogFood();
    }
}

public class Main {
    public static void main(String[] args) {

        AnimalFactory catFactory = new CatFactory();
        Animal cat = catFactory.createAnimal();
        AnimalFood catFood = catFactory.createAnimalFood();

        cat.speak();
        catFood.eat();

        //---------------------------------------//

        AnimalFactory dogFactory = new DogFactory();
        Animal dog = dogFactory.createAnimal();
        AnimalFood dogFood = dogFactory.createAnimalFood();

        dog.speak();
        dogFood.eat();
    }
}

抽象工廠可以方便地建立一系列相關或相互依賴的物件,但其類非常膨脹,在開發過程中用到的還是相對來說比較少的。

5. 最後

文章中所有程式碼大家都可以在以下連結獲取 github

最後此係列會繼續更新,歡迎大家點贊收藏和轉發

相關文章