CodeGym/Blog Java/Ngẫu nhiên/Các mẫu thiết kế: Phương pháp nhà máy

Các mẫu thiết kế: Phương pháp nhà máy

Xuất bản trong nhóm
CHÀO! Hôm nay chúng ta sẽ tiếp tục nghiên cứu về các mẫu thiết kế và chúng ta sẽ thảo luận về mẫu phương thức xuất xưởng. Các mẫu thiết kế: Factory method - 1 Bạn sẽ tìm ra nó là gì và mẫu này phù hợp với những nhiệm vụ nào. Chúng ta sẽ xem xét mẫu thiết kế này trong thực tế và nghiên cứu cấu trúc của nó. Để đảm bảo mọi thứ rõ ràng, bạn cần hiểu các chủ đề sau:
  1. Kế thừa trong Java.
  2. Các phương thức và lớp trừu tượng trong Java

Phương pháp nhà máy giải quyết vấn đề gì?

Tất cả các mẫu thiết kế của nhà máy đều có hai loại người tham gia: người sáng tạo (chính nhà máy) và sản phẩm (đối tượng do nhà máy tạo ra). Hãy tưởng tượng tình huống sau: chúng tôi có một nhà máy sản xuất ô tô mang nhãn hiệu CodeGym. Nó biết cách tạo ra các mô hình ô tô với nhiều loại thân xe khác nhau:
  • xe sedan
  • xe ga
  • những chiếc coupe
Công việc kinh doanh của chúng tôi phát đạt đến mức một ngày đẹp trời, chúng tôi mua lại một nhà sản xuất ô tô khác — OneAuto. Là những chủ doanh nghiệp nhạy bén, chúng tôi không muốn mất bất kỳ khách hàng nào của OneAuto và vì vậy chúng tôi phải đối mặt với nhiệm vụ tái cơ cấu sản xuất để có thể sản xuất:
  • xe sedan CodeGym
  • Toa xe ga CodeGym
  • CodeGym coupe
  • xe sedan OneAuto
  • Xe ga OneAuto
  • OneAuto coupe
Như bạn có thể thấy, thay vì một nhóm sản phẩm, giờ đây chúng tôi có hai nhóm và chúng khác nhau ở một số chi tiết nhất định. Factory method design pattern dành cho khi chúng ta cần tạo các nhóm sản phẩm khác nhau, mỗi nhóm có một số đặc điểm cụ thể. Chúng ta sẽ xem xét nguyên tắc hướng dẫn của mẫu này trong thực tế, dần dần chuyển từ đơn giản sang phức tạp, sử dụng ví dụ về quán cà phê mà chúng ta đã tạo trong một trong những bài học trước .

Một chút về mô hình nhà máy

Hãy để tôi nhắc bạn rằng trước đây chúng tôi đã xây dựng một quán cà phê ảo nhỏ. Với sự trợ giúp của một nhà máy đơn giản, chúng tôi đã học cách tạo ra các loại cà phê khác nhau. Hôm nay chúng ta sẽ làm lại ví dụ này. Hãy nhớ lại quán cà phê của chúng ta trông như thế nào, với nhà máy đơn giản của nó. Chúng tôi đã có một lớp học cà phê:
public class Coffee {
    public void grindCoffee(){
        // Grind the coffee
    }
    public void makeCoffee(){
        // Brew the coffee
    }
    public void pourIntoCup(){
        // Pour into a cup
    }
}
Và một số lớp con tương ứng với các loại cà phê cụ thể mà nhà máy chúng tôi sản xuất được:
public class Americano extends Coffee {}
public class Cappuccino extends Coffee {}
public class CaffeLatte extends Coffee {}
public class Espresso extends Coffee {}
Chúng tôi đã tạo một enum để dễ dàng đặt hàng:
public enum CoffeeType {
    ESPRESSO,
    AMERICANO,
    CAFFE_LATTE,
    CAPPUCCINO
}
Bản thân nhà máy cà phê trông như thế này:
public class SimpleCoffeeFactory {
    public Coffee createCoffee(CoffeeType type) {
        Coffee coffee = null;

        switch (type) {
            case AMERICANO:
                coffee = new Americano();
                break;
            case ESPRESSO:
                coffee = new Espresso();
                break;
            case CAPPUCCINO:
                coffee = new Cappuccino();
                break;
            case CAFFE_LATTE:
                coffee = new CaffeLatte();
                break;
        }

        return coffee;
    }
}
Và cuối cùng, quán cà phê trông như thế này:
public class CoffeeShop {

    private final SimpleCoffeeFactory coffeeFactory;

    public CoffeeShop(SimpleCoffeeFactory coffeeFactory) {
        this.coffeeFactory = coffeeFactory;
    }

    public Coffee orderCoffee(CoffeeType type) {
        Coffee coffee = coffeeFactory.createCoffee(type);
        coffee.grindCoffee();
        coffee.makeCoffee();
        coffee.pourIntoCup();

        System.out.println("Here's your coffee! Thanks! Come again!");
        return coffee;
    }
}

Hiện đại hóa một nhà máy đơn giản

Quán cà phê của chúng tôi đang hoạt động rất tốt. Nhiều đến mức chúng tôi đang xem xét mở rộng. Chúng tôi muốn mở một số địa điểm mới. Chúng tôi táo bạo và dám nghĩ dám làm, vì vậy chúng tôi sẽ không tạo ra những quán cà phê nhàm chán. Chúng tôi muốn mỗi cửa hàng có một sự thay đổi đặc biệt. Theo đó, để bắt đầu, chúng tôi sẽ mở hai địa điểm: một ở Ý và một ở Mỹ. Những thay đổi này sẽ không chỉ ảnh hưởng đến thiết kế nội thất mà còn ảnh hưởng đến đồ uống được cung cấp:
  • trong quán cà phê Ý, chúng tôi sẽ sử dụng các nhãn hiệu cà phê độc quyền của Ý, với cách xay và rang đặc biệt.
  • địa điểm ở Mỹ sẽ có những phần ăn lớn hơn và chúng tôi sẽ phục vụ kẹo dẻo với mỗi đơn hàng.
Điều duy nhất không thay đổi là mô hình kinh doanh của chúng tôi, mô hình này đã được chứng minh là xuất sắc. Về mã, đây là những gì xảy ra. Chúng tôi có 4 lớp tương ứng với các sản phẩm của mình:
public class Americano extends Coffee {}
public class Cappuccino extends Coffee {}
public class CaffeLatte extends Coffee {}
public class Espresso extends Coffee {}
Nhưng bây giờ chúng ta sẽ có 8:
public class ItalianStyleAmericano extends Coffee {}
public class ItalianStyleCappucino extends Coffee {}
public class ItalianStyleCaffeLatte extends Coffee {}
public class ItalianStyleEspresso extends Coffee {}

public class AmericanStyleAmericano extends Coffee {}
public class AmericanStyleCappucino extends Coffee {}
public class AmericanStyleCaffeLatte extends Coffee {}
public class AmericanStyleEspresso extends Coffee {}
Vì chúng tôi muốn giữ nguyên mô hình kinh doanh hiện tại nên chúng tôi muốn phương orderCoffee(CoffeeType type)pháp này trải qua càng ít thay đổi càng tốt. Hãy nhìn vào nó:
public Coffee orderCoffee(CoffeeType type) {
    Coffee coffee = coffeeFactory.createCoffee(type);
    coffee.grindCoffee();
    coffee.makeCoffee();
    coffee.pourIntoCup();

    System.out.println("Here's your coffee! Thanks! Come again!");
    return coffee;
}
Chúng ta có những lựa chọn nào? Chà, chúng ta đã biết cách viết nhà máy rồi phải không? Điều đơn giản nhất ngay lập tức xuất hiện trong đầu là viết hai nhà máy tương tự, sau đó chuyển cách triển khai mong muốn cho người xây dựng quán cà phê của chúng ta. Bằng cách này, đẳng cấp của quán cà phê sẽ không thay đổi. Trước tiên, chúng ta cần tạo một lớp nhà máy mới, làm cho nó kế thừa nhà máy đơn giản của chúng ta, sau đó ghi đè phương createCoffee(CoffeeType type)thức. Hãy viết các nhà máy để tạo ra cà phê kiểu Ý và cà phê kiểu Mỹ:
public class SimpleItalianCoffeeFactory extends SimpleCoffeeFactory {

    @Override
    public Coffee createCoffee(CoffeeType type) {
        Coffee coffee = null;
        switch (type) {
            case AMERICANO:
                coffee = new ItalianStyleAmericano();
                break;
            case ESPRESSO:
                coffee = new ItalianStyleEspresso();
                break;
            case CAPPUCCINO:
                coffee = new ItalianStyleCappuccino();
                break;
            case CAFFE_LATTE:
                coffee = new ItalianStyleCaffeLatte();
                break;
        }
        return coffee;
    }
}

public class SimpleAmericanCoffeeFactory extends SimpleCoffeeFactory{

    @Override
    public Coffee createCoffee (CoffeeType type) {
        Coffee coffee = null;

        switch (type) {
            case AMERICANO:
                coffee = new AmericanStyleAmericano();
                break;
            case ESPRESSO:
                coffee = new AmericanStyleEspresso();
                break;
            case CAPPUCCINO:
                coffee = new AmericanStyleCappuccino();
                break;
            case CAFFE_LATTE:
                coffee = new AmericanStyleCaffeLatte();
                break;
        }

        return coffee;
    }

}
Bây giờ chúng ta có thể chuyển cài đặt nhà máy mong muốn cho CoffeeShop. Hãy xem mã đặt hàng cà phê từ các cửa hàng cà phê khác nhau sẽ như thế nào. Ví dụ: cà phê cappuccino kiểu Ý và kiểu Mỹ:
public class Main {
    public static void main(String[] args) {
        /*
            Order an Italian-style cappuccino:
            1. Create a factory for making Italian coffee
            2. Create a new coffee shop, passing the Italian coffee factory to it through the constructor
            3. Order our coffee
         */
        SimpleItalianCoffeeFactory italianCoffeeFactory = new SimpleItalianCoffeeFactory();
        CoffeeShop italianCoffeeShop = new CoffeeShop(italianCoffeeFactory);
        italianCoffeeShop.orderCoffee(CoffeeType.CAPPUCCINO);


         /*
            Order an American-style cappuccino
            1. Create a factory for making American coffee
            2. Create a new coffee shop, passing the American coffee factory to it through the constructor
            3. Order our coffee
         */
        SimpleAmericanCoffeeFactory americanCoffeeFactory = new SimpleAmericanCoffeeFactory();
        CoffeeShop americanCoffeeShop = new CoffeeShop(americanCoffeeFactory);
        americanCoffeeShop.orderCoffee(CoffeeType.CAPPUCCINO);
    }
}
Chúng tôi đã tạo ra hai cửa hàng cà phê khác nhau, chuyển nhà máy mong muốn cho mỗi cửa hàng. Một mặt, chúng tôi đã hoàn thành mục tiêu của mình, nhưng mặt khác... Bằng cách nào đó, điều này không phù hợp với các doanh nhân... Hãy tìm ra điều gì sai. Đầu tiên, sự phong phú của các nhà máy. Cái gì? Giờ đây, đối với mọi địa điểm mới, chúng tôi phải tạo nhà máy của riêng mình và ngoài ra, đảm bảo rằng nhà máy có liên quan được chuyển cho người xây dựng khi tạo quán cà phê? Thứ hai, nó vẫn là một nhà máy đơn giản. Chỉ cần hiện đại hóa một chút. Nhưng chúng ta ở đây để học một khuôn mẫu mới. Thứ ba, không phải là một cách tiếp cận khác có thể? Sẽ thật tuyệt nếu chúng ta có thể đưa tất cả các vấn đề liên quan đến pha chế cà phê vàoCoffeeShopđẳng cấp bằng cách liên kết các quy trình tạo ra cà phê và phục vụ các đơn đặt hàng, đồng thời duy trì đủ tính linh hoạt để tạo ra nhiều phong cách cà phê khác nhau. Câu trả lời là có, chúng ta có thể. Đây được gọi là mẫu thiết kế phương thức xuất xưởng.

Từ một nhà máy đơn giản đến một phương pháp nhà máy

Để giải quyết công việc hiệu quả nhất có thể:
  1. Chúng tôi trả lại createCoffee(CoffeeType type)phương thức cho CoffeeShoplớp.
  2. Chúng ta sẽ làm cho phương thức này trở nên trừu tượng.
  3. Bản thân lớp CoffeeShopsẽ trở nên trừu tượng.
  4. Lớp CoffeeShopsẽ có các lớp con.
Vâng, bạn ạ. Quán cà phê Ý không gì khác hơn là hậu duệ của CoffeeShoplớp thực hiện createCoffee(CoffeeType type)phương pháp phù hợp với truyền thống tốt nhất của baristas Ý. Bây giờ, từng bước một. Bước 1. Tạo Coffeelớp trừu tượng. Chúng tôi có hai dòng sản phẩm khác nhau. Tuy nhiên, cà phê Ý và cà phê Mỹ có một tổ tiên chung - đẳng Coffeecấp. Nó sẽ là thích hợp để làm cho nó trừu tượng:
public abstract class Coffee {
    public void makeCoffee(){
        // Brew the coffee
    }
    public void pourIntoCup(){
        // Pour into a cup
    }
}
Bước 2. Tạo CoffeeShoptrừu tượng, với một createCoffee(CoffeeType type)phương thức trừu tượng
public abstract class CoffeeShop {

    public Coffee orderCoffee(CoffeeType type) {
        Coffee coffee = createCoffee(type);

        coffee.makeCoffee();
        coffee.pourIntoCup();

        System.out.println("Here's your coffee! Thanks! Come again!");
        return coffee;
    }

    protected abstract Coffee createCoffee(CoffeeType type);
}
Bước 3. Tạo một quán cà phê kiểu Ý, là hậu duệ của quán cà phê trừu tượng. Chúng tôi triển khai createCoffee(CoffeeType type)phương pháp trong đó, có tính đến các chi tiết cụ thể của người nhận ở Ý.
public class ItalianCoffeeShop extends CoffeeShop {

    @Override
    public Coffee createCoffee (CoffeeType type) {
        Coffee coffee = null;
        switch (type) {
            case AMERICANO:
                coffee = new ItalianStyleAmericano();
                break;
            case ESPRESSO:
                coffee = new ItalianStyleEspresso();
                break;
            case CAPPUCCINO:
                coffee = new ItalianStyleCappuccino();
                break;
            case CAFFE_LATTE:
                coffee = new ItalianStyleCaffeLatte();
                break;
        }
        return coffee;
    }
}
Bước 4. Ta làm tương tự với quán cà phê phong cách Mỹ
public class AmericanCoffeeShop extends CoffeeShop {
    @Override
    public Coffee createCoffee(CoffeeType type) {
        Coffee coffee = null;

        switch (type) {
            case AMERICANO:
                coffee = new AmericanStyleAmericano();
                break;
            case ESPRESSO:
                coffee = new AmericanStyleEspresso();
                break;
            case CAPPUCCINO:
                coffee = new AmericanStyleCappuccino();
                break;
            case CAFFE_LATTE:
                coffee = new AmericanStyleCaffeLatte();
                break;
        }

        return coffee;
    }
}
Bước 5. Kiểm tra xem latte của Mỹ và Ý trông như thế nào:
public class Main {
    public static void main(String[] args) {
        CoffeeShop italianCoffeeShop = new ItalianCoffeeShop();
        italianCoffeeShop.orderCoffee(CoffeeType.CAFFE_LATTE);

        CoffeeShop americanCoffeeShop = new AmericanCoffeeShop();
        americanCoffeeShop.orderCoffee(CoffeeType.CAFFE_LATTE);
    }
}
Chúc mừng. Chúng tôi vừa triển khai mẫu thiết kế phương pháp nhà máy bằng cách sử dụng quán cà phê của mình làm ví dụ.

Nguyên tắc đằng sau phương pháp nhà máy

Bây giờ hãy xem xét chi tiết hơn những gì chúng ta có. Sơ đồ dưới đây cho thấy các lớp kết quả. Các khối màu xanh lá cây là các lớp người sáng tạo và các khối màu xanh lam là các lớp sản phẩm. Các mẫu thiết kế: Factory method - 2Chúng ta có thể đưa ra kết luận gì?
  1. Tất cả các sản phẩm là triển khai của Coffeelớp trừu tượng.
  2. Tất cả những người tạo là triển khai của CoffeeShoplớp trừu tượng.
  3. Chúng tôi thấy hai hệ thống phân cấp lớp song song:
    • Thứ bậc của sản phẩm. Chúng tôi thấy hậu duệ người Ý và hậu duệ người Mỹ
    • Thứ bậc của người sáng tạo. Chúng tôi thấy hậu duệ người Ý và hậu duệ người Mỹ
  4. Lớp CoffeeShopcha không có thông tin về sản phẩm cụ thể ( Coffee) nào sẽ được tạo.
  5. Lớp CoffeeShopcha ủy thác việc tạo ra một sản phẩm cụ thể cho các lớp con của nó.
  6. Mỗi hậu duệ của CoffeeShoplớp thực hiện một createCoffee()phương thức xuất xưởng phù hợp với các tính năng cụ thể của riêng nó. Nói cách khác, việc triển khai các lớp nhà sản xuất chuẩn bị các sản phẩm cụ thể dựa trên các chi tiết cụ thể của lớp nhà sản xuất.
Bây giờ bạn đã sẵn sàng cho định nghĩa về mẫu phương thức xuất xưởng . Mẫu phương thức xuất xưởng xác định một giao diện để tạo một đối tượng, nhưng cho phép các lớp con chọn lớp của đối tượng được tạo. Do đó, một phương thức xuất xưởng ủy thác việc tạo một thể hiện cho các lớp con. Nói chung, việc ghi nhớ định nghĩa không quan trọng bằng việc hiểu nó hoạt động như thế nào.

Cấu trúc của một phương pháp nhà máy

Các mẫu thiết kế: Factory method - 3Sơ đồ trên cho thấy cấu trúc chung của mẫu phương thức xuất xưởng. Điều gì khác là quan trọng ở đây?
  1. Lớp Creator triển khai tất cả các phương thức tương tác với sản phẩm, ngoại trừ phương thức xuất xưởng.
  2. Phương thức trừu tượng factoryMethod()phải được thực hiện bởi tất cả các hậu duệ của Creatorlớp.
  3. Lớp ConcreteCreatorthực hiện factoryMethod()phương thức trực tiếp tạo ra sản phẩm.
  4. Lớp này chịu trách nhiệm tạo ra các sản phẩm cụ thể. Đây là lớp duy nhất có thông tin về việc tạo ra các sản phẩm này.
  5. Tất cả các sản phẩm phải triển khai một giao diện chung, tức là chúng phải là hậu duệ của một lớp sản phẩm chung. Điều này là cần thiết để các lớp sử dụng sản phẩm có thể hoạt động trên chúng dưới dạng trừu tượng, thay vì triển khai cụ thể.

Bài tập về nhà

Hôm nay chúng ta đã làm khá nhiều việc và nghiên cứu mẫu thiết kế theo phương pháp nhà máy. Đã đến lúc củng cố tài liệu! Bài tập 1. Làm công việc mở thêm một quán cà phê. Đó có thể là một quán cà phê kiểu Anh hoặc kiểu Tây Ban Nha. Hoặc thậm chí là phong cách tàu vũ trụ. Thêm màu thực phẩm vào cà phê để cà phê phát sáng, và cà phê của bạn sẽ đơn giản là khác hẳn thế giới này! Bài tập 2. Trong bài học trước , bạn đã có một bài tập trong đó bạn tạo một quán sushi ảo hoặc một tiệm bánh pizza ảo. Bây giờ bài tập của bạn là không đứng yên. Hôm nay bạn đã học cách sử dụng mẫu phương thức xuất xưởng để tạo lợi thế cho mình. Đã đến lúc sử dụng kiến ​​thức này và mở rộng kinh doanh của riêng bạn;)
Bình luận
  • Phổ biến
  • Mới
Bạn phải đăng nhập để đăng nhận xet
Trang này chưa có bất kỳ bình luận nào