Factory Method là một trong những design patterns phổ biến mà lập trình viên Java không thể bỏ qua. Trong bài viết này, chúng ta sẽ tìm hiểu về ý nghĩa và cách thức hoạt động của Factory Method, cũng như cách mà nó được ứng dụng trong các thư viện Java nổi bật. Hãy cùng bắt đầu hành trình khám phá này!
I. Khái niệm về Factory Method và kiến trúc tổng quát
Theo các tác giả nổi tiếng GoF trong cuốn Design Patterns: Elements of Reusable Object-Oriented Software, Factory Method được định nghĩa như sau:
Định nghĩa một giao diện để tạo ra một đối tượng, nhưng để các lớp con quyết định lớp nào sẽ được khởi tạo. Factory Method cho phép một lớp hoãn việc tạo đối tượng cho các lớp con.
— GoF
Nhóm: Creational Pattern
Cấu trúc tổng quát của Factory Method
- Creator: Khai báo phương thức
factoryMethod()
. - Concrete Creator: Override phương thức
factoryMethod()
để trả về instance của mộtConcrete Product
. - Product: Định nghĩa giao diện chung được sử dụng bởi các
Concrete Creator
. - Concrete Product: Thực hiện giao diện
Product
.
Nói một cách đơn giản, Factory Method chuyển giao trách nhiệm khởi tạo đối tượng cho các lớp con. Bài viết này không dài dòng về lý thuyết, chúng ta sẽ đi vào các ví dụ cụ thể để tìm hiểu cách thức ứng dụng Factory Method trong các thư viện Java.
II. Cách các thư viện Java sử dụng Factory Method
Dưới đây là một số ví dụ điển hình về việc áp dụng Factory Method trong các thư viện Java:
1. URLStreamHandlerFactory#createURLStreamHandler()
Phương thức createURLStreamHandler
của URLStreamHandlerFactory
là một ví dụ điển hình. Nó trả về một URLStreamHandler
dựa trên tham số đầu vào.
URLStreamHandlerFactory
là Creator.factoryMethod()
tương ứng vớicreateURLStreamHandler
.URLStreamHandler
là Product.DefaultFactory
là Concrete Creator.
Các Concrete Product
sẽ là các lớp con của URLStreamHandler
trong các package như sun.net.www.protocol.file.Handler
, sun.net.www.protocol.jar.Handler
, và sun.net.www.protocol.jrt.Handler
.
Cấu trúc kinh điển này cho thấy rõ ràng cách thức mà Factory Method hoạt động trong các thư viện Java.
2. Calendar#getInstance()
Phương thức getInstance()
trong lớp java.util.Calendar
là một biến thể thú vị của Factory Method.
Thay vì phụ thuộc vào một Creator
, Calendar
tự tạo instance mới thông qua một static method – getInstance()
.
Ví dụ, khi tham số locale.getUnicodeLocaleType
bằng buddhist
, nó trả về một instance mới của BuddhistCalendar
. Nếu là japanese
, nó sẽ trả về JapaneseImperialCalendar
. Việc sử dụng getInstance()
giúp Client
nhận được các subclass của Calendar
tương ứng.
3. NumberFormat#getInstance()
Tương tự như ví dụ trên, NumberFormat#getInstance()
cũng không cần đến Creator
. Đây là một phương thức tĩnh trả về một Product
theo cách phân loại, không nhất thiết phải khởi tạo lớp con nhưng vẫn cho ra các định dạng khác nhau như số, phần trăm hoặc tiền tệ.
4. CharSet#forName()
Phương thức CharSet.forName()
minh họa cách Factory Method có thể tối ưu tài nguyên. Bằng việc sử dụng cache, phương thức này trả về một instance đã được tạo sẵn nếu tham số đầu vào đã được khởi tạo trước đó, giúp tiết kiệm bộ nhớ cho những yêu cầu sau này.
III. Kết luận
Qua bài viết này, hy vọng bạn đọc đã có cái nhìn sâu sắc về cách mà các thư viện Java áp dụng Factory Method. Từ các ví dụ cụ thể như URLStreamHandlerFactory
, Calendar
, và những biến thể độc đáo như CharSet
hay NumberFormat
, hy vọng bạn sẽ có thêm kiến thức và khả năng áp dụng pattern này trong thực tế. Hãy tiếp tục theo dõi series bài viết để khám phá thêm nhiều điều thú vị về các design pattern trong các thư viện Java khác.
IV. Tài liệu tham khảo
- Refactoring Guru: refactoring.guru/design-patterns
- Head First Design Pattern - O'Reilly
- Design Patterns: Elements of Reusable Object-Oriented Software - GoF
Nếu bạn thấy bài viết này hữu ích, đừng ngần ngại nhấn upvote hoặc để lại bình luận nếu có ý kiến gì cần trao đổi. Thêm vào đó, bạn có thể tham khảo thêm nhiều bài viết khác trên blog cá nhân của tôi hoặc theo dõi tôi trên LinkedIn.
source: viblo