JavaRush /Blog Java /Random-VI /Mẫu thiết kế: Tóm tắtFactory

Mẫu thiết kế: Tóm tắtFactory

Xuất bản trong nhóm
Xin chào! Hôm nay chúng ta sẽ tiếp tục nghiên cứu các mẫu thiết kế và nói về nhà máy trừu tượng . Mẫu thiết kế: Tóm tắtFactory - 1Những gì chúng ta sẽ làm trong buổi thuyết trình:
  • Hãy cùng thảo luận về abstract Factory là gì và mô hình này giải quyết được vấn đề gì;
  • chúng tôi sẽ tạo khuôn khổ của một ứng dụng đa nền tảng để đặt cà phê với giao diện người dùng;
  • Hãy nghiên cứu hướng dẫn sử dụng mẫu này bằng sơ đồ và mã;
  • Như một phần thưởng, có một quả trứng Phục sinh ẩn trong bài giảng, nhờ đó bạn sẽ học cách xác định tên của hệ điều hành bằng Java và tùy thuộc vào kết quả, hãy thực hiện một hoặc một hành động khác.
Để hiểu đầy đủ về mô hình này, bạn cần hiểu rõ về các chủ đề sau:
  • kế thừa trong Java;
  • các lớp và phương thức trừu tượng trong Java.

Mô hình nhà máy trừu tượng giải quyết được những vấn đề gì?

Nhà máy trừu tượng, giống như tất cả các mẫu nhà máy, giúp chúng ta tổ chức việc tạo các đối tượng mới một cách chính xác. Với sự trợ giúp của nó, chúng tôi quản lý việc "phát hành" nhiều nhóm đối tượng được kết nối với nhau. Nhiều họ của các đối tượng có liên quan đến nhau...Nó là gì? Đừng lo lắng: trên thực tế, mọi thứ đơn giản hơn bạn tưởng. Hãy bắt đầu với những gì có thể là một nhóm các đối tượng có liên quan? Giả sử bạn và tôi đang phát triển một chiến lược và có một số đơn vị chiến đấu trong đó:
  • bộ binh;
  • kỵ sĩ;
  • cung thủ.
Các loại đơn vị chiến đấu này có liên quan với nhau vì chúng phục vụ trong cùng một quân đội. Chúng ta có thể nói rằng các danh mục được liệt kê ở trên là một họ các đối tượng có liên quan với nhau. Thế là xong. Nhưng mẫu nhà máy trừu tượng được sử dụng để tổ chức việc tạo ra nhiều họ đối tượng được kết nối với nhau. Không có gì phức tạp ở đây cả. Hãy tiếp tục ví dụ với chiến lược. Họ thường có nhiều mặt đối lập khác nhau. Các đơn vị chiến đấu của các bên khác nhau có thể có hình dáng khác nhau đáng kể. Bộ binh, kỵ binh và cung thủ của quân đội La Mã không giống như bộ binh, kỵ binh và cung thủ của người Viking. Trong khuôn khổ chiến lược, binh lính của các đội quân khác nhau là những nhóm đối tượng khác nhau có mối liên hệ với nhau. Sẽ thật buồn cười nếu, do nhầm lẫn của người lập trình, một người lính mặc quân phục Pháp từ thời Napoléon, với súng hỏa mai sẵn sàng, đang đi loanh quanh giữa bộ binh La Mã. Để giải quyết vấn đề đó cần phải có mẫu thiết kế nhà máy trừu tượng. Không, không phải vấn đề bối rối khi du hành thời gian, mà là việc tạo ra nhiều nhóm đối tượng liên kết với nhau. Một abstract Factory cung cấp một giao diện để tạo ra tất cả các sản phẩm hiện có (đối tượng gia đình). Một abstract Factory thường có nhiều triển khai. Mỗi người trong số họ chịu trách nhiệm tạo ra các sản phẩm của một trong các biến thể. Là một phần của chiến lược, chúng tôi sẽ có một nhà máy trừu tượng tạo ra bộ binh, cung thủ và kỵ binh trừu tượng, cũng như việc triển khai nhà máy này. Một nhà máy sản xuất lính lê dương La Mã và chẳng hạn như một nhà máy sản xuất các chiến binh Carthage. Trừu tượng hóa là nguyên tắc quan trọng nhất của mẫu này. Khách hàng của nhà máy chỉ làm việc với nó và với các sản phẩm thông qua các giao diện trừu tượng. Do đó, chúng tôi không cần phải suy nghĩ về loại chiến binh mà chúng tôi hiện đang tạo ra mà chuyển trách nhiệm này sang một số hoạt động triển khai cụ thể của nhà máy trừu tượng.

Chúng tôi tiếp tục tự động hóa quán cà phê

Trong bài giảng trước, chúng tôi đã nghiên cứu mô hình phương pháp nhà máy, nhờ đó chúng tôi có thể mở rộng kinh doanh cà phê và mở một số điểm bán cà phê mới. Hôm nay chúng tôi sẽ tiếp tục công việc hiện đại hóa hoạt động kinh doanh của mình. Sử dụng mẫu nhà máy trừu tượng, chúng tôi sẽ đặt nền tảng cho một ứng dụng máy tính để bàn mới để đặt hàng cà phê trực tuyến. Khi viết một ứng dụng cho máy tính để bàn, chúng ta phải luôn nghĩ đến tính đa nền tảng. Ứng dụng của chúng tôi sẽ hoạt động trên cả macOS và Windows (spoiler: Linux sẽ để lại cho bạn làm bài tập về nhà). Ứng dụng của chúng ta sẽ trông như thế nào? Khá đơn giản: nó sẽ là một biểu mẫu bao gồm trường văn bản, trường chọn và nút. Nếu bạn có kinh nghiệm sử dụng các hệ điều hành khác nhau, bạn chắc chắn nhận thấy rằng trên Windows, các nút được hiển thị khác với trên Mac. Giống như mọi thứ khác... Vì vậy, hãy bắt đầu. Trong vai trò của dòng sản phẩm, như bạn có thể đã hiểu, chúng ta sẽ có các thành phần giao diện đồ họa:
  • nút;
  • Trường văn bản;
  • các trường để lựa chọn.
Tuyên bố từ chối trách nhiệm. Trong mỗi giao diện, chúng ta có thể định nghĩa các phương thức như onClick, onValueChangedhoặc onInputChanged. Những thứ kia. các phương thức sẽ cho phép chúng ta xử lý các sự kiện khác nhau (nhấp vào nút, nhập văn bản, chọn giá trị trong hộp chọn). Tất cả điều này được cố tình bỏ qua để không làm quá tải ví dụ và làm cho nó trực quan hơn khi nghiên cứu mô hình nhà máy. Hãy xác định giao diện trừu tượng cho các sản phẩm của chúng tôi:
public interface Button {}
public interface Select {}
public interface TextField {}
Đối với mỗi hệ điều hành, chúng ta phải tạo các thành phần giao diện theo phong cách của hệ điều hành đó. Chúng tôi viết cho Windows và MacOS. Hãy tạo các triển khai cho Windows:
public class WindowsButton implements Button {
}

public class WindowsSelect implements Select {
}

public class WindowsTextField implements TextField {
}
Bây giờ tương tự cho MacOS:
public class MacButton implements Button {
}

public class MacSelect implements Select {
}

public class MacTextField implements TextField {
}
Tuyệt vời. Bây giờ chúng ta có thể bắt đầu nhà máy trừu tượng của mình, nơi sẽ tạo ra tất cả các loại sản phẩm trừu tượng hiện có:
public interface GUIFactory {

    Button createButton();
    TextField createTextField();
    Select createSelect();

}
Hoàn hảo. Như bạn có thể thấy, cho đến nay không có gì phức tạp. Sau đó mọi thứ chỉ đơn giản như vậy. Bằng cách tương tự với các sản phẩm, chúng tôi tạo ra các triển khai khác nhau của nhà máy cho từng hệ điều hành. Hãy bắt đầu với Windows:
public class WindowsGUIFactory implements GUIFactory {
    public WindowsGUIFactory() {
        System.out.println("Creating gui factory for Windows OS");
    }

    public Button createButton() {
        System.out.println("Creating Button for Windows OS");
        return new WindowsButton();
    }

    public TextField createTextField() {
        System.out.println("Creating TextField for Windows OS");
        return new WindowsTextField();
    }

    public Select createSelect() {
        System.out.println("Creating Select for Windows OS");
        return new WindowsSelect();
    }
}
Đầu ra của bảng điều khiển bên trong các phương thức và hàm tạo đã được thêm vào để minh họa rõ hơn cách thức hoạt động của nó. Bây giờ dành cho macOS:
public class MacGUIFactory implements GUIFactory {
    public MacGUIFactory() {
        System.out.println("Creating gui factory for macOS");
    }

    @Override
    public Button createButton() {
        System.out.println("Creating Button for macOS");
        return new MacButton();
    }

    @Override
    public TextField createTextField() {
        System.out.println("Creating TextField for macOS");
        return new MacTextField();
    }

    @Override
    public Select createSelect() {
        System.out.println("Creating Select for macOS");
        return new MacSelect();
    }
}
Lưu ý: mỗi phương thức, theo chữ ký của nó, trả về một kiểu trừu tượng. Nhưng bên trong phương thức này, chúng tôi tạo ra một triển khai cụ thể của sản phẩm. Đây là nơi duy nhất chúng tôi kiểm soát việc tạo các phiên bản cụ thể. Bây giờ là lúc viết lớp biểu mẫu. Đây là một lớp Java có các trường là các thành phần giao diện:
public class OrderCoffeeForm {
    private final TextField customerNameTextField;
    private final Select coffeTypeSelect;
    private final Button orderButton;

    public OrderCoffeeForm(GUIFactory factory) {
        System.out.println("Creating order coffee form");
        customerNameTextField = factory.createTextField();
        coffeTypeSelect = factory.createSelect();
        orderButton = factory.createButton();
    }
}
Một nhà máy trừu tượng được chuyển tới hàm tạo biểu mẫu để tạo các thành phần giao diện. Chúng tôi sẽ chuyển việc triển khai nhà máy cần thiết cho hàm tạo để chúng tôi có thể tạo các thành phần giao diện cho một hệ điều hành cụ thể.
public class Application {
    private OrderCoffeeForm orderCoffeeForm;

    public void drawOrderCoffeeForm() {
        // Определим Name операционной системы, получив meaning системной проперти через System.getProperty
        String osName = System.getProperty("os.name").toLowerCase();
        GUIFactory guiFactory;

        if (osName.startsWith("win")) { // Для windows
            guiFactory = new WindowsGUIFactory();
        } else if (osName.startsWith("mac")) { // Для mac
            guiFactory = new MacGUIFactory();
        } else {
            System.out.println("Unknown OS, can't draw form :( ");
            return;
        }
        orderCoffeeForm = new OrderCoffeeForm(guiFactory);
    }

    public static void main(String[] args) {
        Application application = new Application();
        application.drawOrderCoffeeForm();
    }
}
Nếu chúng ta chạy ứng dụng trên Windows, chúng ta sẽ nhận được kết quả như sau:

Creating gui factory for Windows OS
Creating order coffee form
Creating TextField for Windows OS
Creating Select for Windows OS
Creating Button for Windows OS
Trên máy Mac, đầu ra sẽ như sau:

Creating gui factory for macOS
Creating order coffee form
Creating TextField for macOS
Creating Select for macOS
Creating Button for macOS
Trên Linux:

Unknown OS, can't draw form :( 
Vâng, bạn và tôi rút ra kết luận sau đây. Chúng tôi đã viết một khung cho ứng dụng GUI để tạo chính xác các thành phần giao diện phù hợp với một hệ điều hành nhất định. Hãy để chúng tôi lặp lại ngắn gọn những gì chúng tôi đã tạo ra:
  • Nhóm sản phẩm: trường nhập, trường lựa chọn và nút.
  • Nhiều cách triển khai khác nhau của dòng sản phẩm này dành cho Windows và macOS.
  • Một nhà máy trừu tượng, trong đó chúng tôi xác định giao diện để tạo ra các sản phẩm của mình.
  • Hai hoạt động triển khai của nhà máy của chúng tôi, mỗi hoạt động chịu trách nhiệm tạo ra một dòng sản phẩm cụ thể.
  • Một biểu mẫu, một lớp Java có các trường là các thành phần giao diện trừu tượng được khởi tạo trong hàm tạo với các giá trị bắt buộc bằng cách sử dụng một nhà máy trừu tượng.
  • Lớp ứng dụng. Bên trong nó, chúng ta tạo một biểu mẫu để chuyển việc triển khai cần thiết của nhà máy cho hàm tạo.
Tổng cộng: chúng tôi đã triển khai mẫu nhà máy trừu tượng.

Nhà máy trừu tượng: hướng dẫn sử dụng

Tóm tắt Factory là một mẫu thiết kế để quản lý việc tạo ra các dòng sản phẩm khác nhau mà không bị ràng buộc với các lớp sản phẩm cụ thể. Khi sử dụng mẫu này, bạn phải:
  1. Tự xác định các dòng sản phẩm. Giả sử chúng ta có hai trong số chúng:
    • SpecificProductA1,SpecificProductB1
    • SpecificProductA2,SpecificProductB2
  2. Đối với mỗi sản phẩm trong dòng sản phẩm, hãy xác định một lớp (giao diện) trừu tượng. Trong trường hợp của chúng tôi đó là:
    • ProductA
    • ProductB
  3. Trong mỗi dòng sản phẩm, mỗi sản phẩm phải triển khai giao diện được xác định ở bước 2.
  4. Tạo một abstract Factory, với các phương thức create cho từng sản phẩm được xác định ở bước 2. Trong trường hợp của chúng ta, các phương thức này sẽ là:
    • ProductA createProductA();
    • ProductB createProductB();
  5. Tạo các triển khai của nhà máy trừu tượng để mỗi triển khai kiểm soát việc tạo ra các sản phẩm cùng dòng. Để làm được điều này, bên trong mỗi triển khai của abstract Factory, cần phải triển khai tất cả các phương thức create để việc triển khai cụ thể các sản phẩm được tạo và trả về bên trong chúng.
Dưới đây là sơ đồ UML minh họa các hướng dẫn được mô tả ở trên: Mẫu thiết kế: Tóm tắtFactory - 3Bây giờ hãy viết mã cho hướng dẫn này:
// Определим общие интерфейсы продуктов
public interface ProductA {}
public interface ProductB {}

// Создадим различные реализации (семейства) наших продуктов
public class SpecificProductA1 implements ProductA {}
public class SpecificProductB1 implements ProductB {}

public class SpecificProductA2 implements ProductA {}
public class SpecificProductB2 implements ProductB {}

// Создадим абстрактную фабрику
public interface AbstractFactory {
    ProductA createProductA();
    ProductB createProductB();
}

// Создадим реализацию абстрактной фабрики для создания продуктов семейства 1
public class SpecificFactory1 implements AbstractFactory {

    @Override
    public ProductA createProductA() {
        return new SpecificProductA1();
    }

    @Override
    public ProductB createProductB() {
        return new SpecificProductB1();
    }
}

// Создадим реализацию абстрактной фабрики для создания продуктов семейства 1
public class SpecificFactory2 implements AbstractFactory {

    @Override
    public ProductA createProductA() {
        return new SpecificProductA2();
    }

    @Override
    public ProductB createProductB() {
        return new SpecificProductB2();
    }
}

Bài tập về nhà

Để củng cố tài liệu, bạn có thể làm 2 việc:
  1. Cải thiện ứng dụng đặt hàng cà phê để nó hoạt động trên Linux.
  2. Tạo nhà máy trừu tượng của riêng bạn để sản xuất các đơn vị của bất kỳ chiến lược nào. Đây có thể là một chiến lược lịch sử với quân đội thực sự hoặc giả tưởng với lũ Orc, người lùn và yêu tinh. Điều chính là bạn thấy nó thú vị. Hãy sáng tạo, đăng ghim lên bảng điều khiển và vui vẻ tìm hiểu các mẫu!
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION