Hướng dẫn Java Design Pattern – Factory Method

Trong bài trước chúng ta đã tìm hiểu về Singleton Design Pattern. Để tiếp tục series về Design Pattern hôm nay chúng ta sẽ tiếp tục tìm hiểu một Pattern khác trong nhóm Creational Design Pattern là Factory Method Design Pattern.

1. Factory Method Pattern là gì?

Factory Method Design Pattern hay gọi ngắn gọn là Factory Pattern là một trong những Pattern thuộc nhóm Creational Design Pattern. Nhiệm vụ của Factory Pattern là quản lý và trả về các đối tượng theo yêu cầu, giúp cho việc khởi tạo đổi tượng một cách linh hoạt hơn.

Trong Factory Pattern, chúng ta tạo đối tượng mà không để lộ logic tạo đối tượng ở phía người dùng và tham chiếu đến đối tượng mới được tạo ra bằng cách sử dụng một interface chung.

Factory Pattern được sử dụng khi có một class cha (super-class) với nhiều class con (sub-class), dựa trên đầu vào và phải trả về 1 trong những class con đó.

2. Cài đặt Factory Pattern như thế nào?

Một Factory Pattern bao gồm các thành phần cơ bản sau:

  • Super Class: môt supper class trong Factory Pattern có thể là một interfaceabstract class hay một class thông thường.
  • Sub Classes: các sub class sẽ implement các phương thức của supper class theo nghiệp vụ riêng của nó.
  • Factory Class: một class chịu tránh nhiệm khởi tạo các đối tượng sub class dựa theo tham số đầu vào. Lưu ý: lớp này là Singleton hoặc cung cấp một public static method cho việc truy xuất và khởi tạo đối tượng. Factory class sử dụng if-else hoặc switch-case để xác định class con đầu ra.

Ví dụ: Tất cả hệ thống Football Club có cung cấp API để truy cập đến hệ thống của họ. Team được giao nhiệm vụ thiết kế một API để client có thể sử dụng dịch vụ của một CLB bất kỳ. Hiện tại, phía client chỉ cần sử dụng dịch vụ của 1 số đội bóng như Becamex Bình Dương, Hoàng Anh Gia Lai, Hà Nội, … Tuy nhiên để dễ mở rộng sau này, và phía client mong muốn không cần phải thay đổi code của họ khi cần sử dụng thêm dịch vụ của đội bóng khác. Với yêu cầu như vậy, chúng ta có thể sử dụng một Pattern phù hợp là Factory Method Pattern.

Hệ thống được minh họa như sau:

Chương trình được cài đặt theo Factory Pattern như sau:

Supper Class:

Java
package com.tmsblog.patterns.creational.factorymethod;

public interface FC {
    String getFCName();
}

Sub Classes:

Java
package com.tmsblog.patterns.creational.factorymethod;
 
public class BECAMEXBinhDuong implements FC {
 
    @Override
    public String getFCName() {
        return "Becamex Binh Duong";
    }
}
Java
package com.tmsblog.patterns.creational.factorymethod;
 
public class HAGL implements FC {
 
    @Override
    public String getFCName() {
        return "Hoang Anh Gia Lai";
    }
}
Java
package com.tmsblog.patterns.creational.factorymethod;
 
public class Hanoi implements FC {
 
    @Override
    public String getFCName() {
        return "Ha Noi";
    }
}

Factory class:

Java
package org.tmsblog.patterns.creational.factorymethod;

import org.tmsblog.enums.FCType;

public class FCFactory {
    public FCFactory() {
    }

    public static final FC getFC(FCType fcType) {
        switch (fcType) {
            case BECAMEX_BD:
                return new BECAMEXBinhDuong();
            case HAGL:
                return new HAGL();
            case HANOI:
                return new Hanoi();
            default:
                throw new IllegalArgumentException("This fc type is unsupported");
        }
    }
}

FC type:

Java
package org.tmsblog.enums;

public enum FCType {
    BECAMEX_BD, HAGL, HANOI
}

Client:

Java
package org.tmsblog.patterns.creational.factorymethod;

import org.tmsblog.enums.FCType;

public class Client {
    public static void main(String[] args) {
        FC fc = FCFactory.getFC(FCType.HANOI);
        System.out.println(fc.getFCName());
    }
}

Như anh em thấy, phía client chỉ cần gọi duy nhất một phương thức FCFactory.getFC() là có thể sử dụng được dịch vụ của một CLB bất kỳ.

Khi hệ thống muốn cung cấp thêm dịch vụ của một CLB khác, chẳng hạn Viettel, thì cần tạo thêm một class mới implement từ interface FC, và thêm vào logic khởi tạo FC trong Factory là xong. Nó không làm ảnh hưởng đến code ở phía Client.

3. Sử dụng Factory Pattern khi nào?

Factory Pattern được sử dụng khi:

  • Chúng ta có một super class với nhiều class con và dựa trên đầu vào, chúng ta cần trả về một class con. Mô hình này giúp chúng ta đưa trách nhiệm của việc khởi tạo một lớp từ phía người dùng (client) sang lớp Factory.
  • Chúng ta không biết sau này sẽ cần đến những lớp con nào nữa. Khi cần mở rộng, hãy tạo ra sub class và implement thêm vào factory method cho việc khởi tạo sub class này.

4. Lợi ích của Factory Pattern là gì?

Lợi ích của Factory Pattern:

  • Factory Pattern giúp giảm sự phụ thuộc giữa các module (loose coupling): cung cấp 1 hướng tiếp cận với Interface thay vì các implement. Giúp chuơng trình độc lập với những lớp cụ thể mà chúng ta cần tạo 1 đối tượng, code ở phía client không bị ảnh hưởng khi thay đổi logic ở factory hay sub class.
  • Mở rộng code dễ dàng hơn: khi cần mở rộng, chỉ việc tạo ra sub class và implement thêm vào factory method.
  • Khởi tạo các Objects mà che giấu đi xử lí logic của việc khởi tạo đấy. Người dùng không biết logic thực sực được khởi tạo bên dưới phương thức factory.
  • Dễ dàng quản lý life cycle của các Object được tạo bởi Factory Pattern.
  • Thống nhất về naming convention: giúp cho các developer có thể hiểu về cấu trúc source code.

Anh em có thể thấy Factory Pattern được áp dụng trong:

  • JDK: java.util.Calendar, ResourceBundle, NumberFormat, …
  • BeanFactory trong Spring Framework.
  • SessionFactory trong Hibernate Framework.

Như vậy tôi đã giới thiệu xong về Factory Method Pattern, hy vọng bài viết sẽ giúp ích cho anh em trong quá trình xây dựng và phát triển ứng dụng. Hẹn gặp lại ở các bài viết tiếp theo.

Tài liệu tham khảo:

0 Shares:
Leave a Reply

Your email address will not be published. Required fields are marked *

You May Also Like