Factory Pattern là một trong những design pattern thuộc nhóm Creational Patterns (mẫu khởi tạo), được sử dụng để tạo đối tượng mà không để lộ logic khởi tạo phức tạp cho người dùng. Factory Pattern cung cấp một giao diện để tạo các đối tượng trong khi cho phép các lớp con quyết định lớp nào sẽ được khởi tạo.

Cơ bản về Factory Pattern

Factory Pattern tập trung vào việc cung cấp một phương pháp hoặc lớp trung gian để tạo ra các đối tượng dựa trên các tham số cụ thể hoặc điều kiện, mà không để lớp khởi tạo trực tiếp các đối tượng đó. Nó thường được sử dụng khi hệ thống có nhiều lớp con hoặc kiểu đối tượng khác nhau nhưng cùng kế thừa từ một lớp cha hoặc interface chung.

Khi nào nên sử dụng Factory Pattern?

Factory Pattern phù hợp khi bạn cần:

  • Khởi tạo các đối tượng phức tạp mà không muốn người dùng biết về chi tiết của quá trình khởi tạo.
  • Có nhiều đối tượng thuộc các lớp khác nhau nhưng cùng chung một giao diện hoặc lớp cha.
  • Muốn dễ dàng mở rộng khi cần thêm các loại đối tượng mới mà không cần thay đổi mã hiện tại.

Ví dụ, nếu bạn có một ứng dụng quản lý phương tiện giao thông (xe hơi, xe tải, xe đạp), mỗi loại phương tiện sẽ có các đặc điểm riêng nhưng lại có cùng một giao diện cơ bản (ví dụ Vehicle). Bạn có thể sử dụng Factory Pattern để tạo ra các đối tượng phương tiện dựa trên tham số đầu vào mà không cần phải khởi tạo từng loại phương tiện riêng lẻ trong mã chính.

Cách hoạt động của Factory Pattern

  1. Factory là một lớp hoặc phương thức chịu trách nhiệm tạo ra các đối tượng cụ thể.
  2. Product là các lớp con hoặc đối tượng cụ thể được tạo ra, và tất cả chúng đều kế thừa từ một lớp hoặc interface chung.
  3. Client (người sử dụng) sẽ không trực tiếp tạo đối tượng mà sẽ thông qua Factory để nhận về đối tượng cần thiết.

Ví dụ mã minh họa Factory Pattern

// Interface Product (Giao diện cho các loại phương tiện)
public interface Vehicle {
    void create();
}

// Concrete Product 1: Xe hơi
public class Car implements Vehicle {
    @Override
    public void create() {
        System.out.println("Xe hơi được tạo.");
    }
}

// Concrete Product 2: Xe tải
public class Truck implements Vehicle {
    @Override
    public void create() {
        System.out.println("Xe tải được tạo.");
    }
}

// Concrete Product 3: Xe đạp
public class Bicycle implements Vehicle {
    @Override
    public void create() {
        System.out.println("Xe đạp được tạo.");
    }
}

// Factory class (Lớp nhà máy tạo ra phương tiện)
public class VehicleFactory {
    // Phương thức tạo phương tiện dựa trên loại
    public Vehicle createVehicle(String vehicleType) {
        if (vehicleType == null) {
            return null;
        }
        if (vehicleType.equalsIgnoreCase("CAR")) {
            return new Car();
        } else if (vehicleType.equalsIgnoreCase("TRUCK")) {
            return new Truck();
        } else if (vehicleType.equalsIgnoreCase("BICYCLE")) {
            return new Bicycle();
        }
        return null;
    }
}

// Sử dụng Factory Pattern
public class Main {
    public static void main(String[] args) {
        VehicleFactory vehicleFactory = new VehicleFactory();

        Vehicle car = vehicleFactory.createVehicle("CAR");
        car.create();

        Vehicle truck = vehicleFactory.createVehicle("TRUCK");
        truck.create();

        Vehicle bicycle = vehicleFactory.createVehicle("BICYCLE");
        bicycle.create();
    }
}

Phân tích mã ví dụ

  1. Vehicle là interface đại diện cho các phương tiện, với phương thức create mà tất cả các lớp con phải triển khai.
  2. Car, Truck, và Bicycle là các lớp con cụ thể của Vehicle, mỗi lớp đều có cách tạo đối tượng riêng biệt.
  3. VehicleFactory là lớp Factory, cung cấp phương thức createVehicle để tạo đối tượng dựa trên loại phương tiện yêu cầu (car, truck, bicycle).
  4. Trong hàm main, chúng ta sử dụng VehicleFactory để tạo ra các đối tượng phương tiện mà không cần phải khởi tạo trực tiếp chúng.

Lợi ích của Factory Pattern

  1. Đóng gói logic khởi tạo: Factory Pattern giúp đóng gói quá trình khởi tạo đối tượng phức tạp và chỉ cung cấp một giao diện đơn giản để tạo đối tượng.
  2. Dễ dàng mở rộng: Nếu muốn thêm một loại đối tượng mới (ví dụ xe máy), bạn chỉ cần tạo một lớp mới kế thừa từ Vehicle và cập nhật Factory mà không phải thay đổi mã của các lớp khác.
  3. Tăng tính linh hoạt và khả năng bảo trì: Bằng cách tách rời quá trình khởi tạo, bạn có thể thay đổi hoặc mở rộng hệ thống dễ dàng mà không làm gián đoạn mã hiện tại.

Kết luận

Factory Pattern là một giải pháp mạnh mẽ và linh hoạt trong việc quản lý việc tạo đối tượng, đặc biệt khi hệ thống có nhiều loại đối tượng cần khởi tạo từ một giao diện hoặc lớp chung. Nó giúp mã dễ bảo trì hơn và giảm thiểu sự phụ thuộc giữa các lớp.