[Design Pattern] Phần 4: Factory Pattern





[Design Pattern] Phần 4: Factory Pattern
Ở phần 4 này chúng ta sẽ tìm hiểu về Factory Pattern, với một cách hiểu đơn giản là loại pattern giúp cho chúng ta không cần phải khởi tạo trực tiếp? Cụ thể nó là thế nào? Vì sao chúng ta lại cần nó? Đừng nôn nóng, chỉ mới bắt đầu thôi. Nào, chúng ta hãy cùng tìm hiểu nào!
Tình huống:
Một công ty công nghệ vừa thành lập đang tuyển người cho các vị trí như sau: Lập trình viên (Developer), Nhân viên kinh doanh (Sale), Kiểm thử phần mềm (Tester). Những người muốn vào làm sẽ đăng ký vào công ty. Về cơ bản chúng ta sẽ thiết kế như sau:

Công ty sẽ có danh sách các nhân viên. Nhân viên nào vào công ty thì sẽ được thêm vào danh sách.
Chúng ta bắt đầu thiết kế các lớp. Đầu tiên là lớp Company

Lớp Company sẽ có tên và danh sách các Employee. Hàm khởi tạo sẽ gán tên và tạo một danh sách rỗng, và khi thêm Employee thì sẽ đưa nó vào danh sách công ty.
Tiếp đến là Employee

Employee là một abstract class và sẽ có tên. Kèm thêm đó là một hàm khởi tạo.
Ba class tiếp theo sẽ kế thừa class Employee



Quá quen thuộc với các bạn rồi nên mình sẽ không giải thích ở đây.
Chúng ta giờ chú ý tới phần test. Chúng ta sẽ tạo ba đối tượng nhân viên thuộc ba ngành khác nhau và thêm vào công ty.

Có vẻ ổn nhỉ.
Nhưng có đôi lúc bạn không muốn khởi tạo new trực tiếp như thế này (Vì sao thì chúng ta sẽ tìm hiểu sau). Chúng ta sẽ muốn nó trông thế này cơ.

EmployeeFactory giống như một “nhà máy” nơi sản xuất ra các employee khi ta gọi phương thức getEmployee() (các tham số chúng ta đưa vào là các thông tin cần thiết cho EmployeeFactory này sản xuất). Chúng ta hãy xây dựng class EmployeeFactory nào

EmployeeFactory sẽ dựa vào job chúng ta nhập vào mà trả về một đối tượng tương ứng.
Bản chất của Factory Design Pattern là tại vị trí client (người chỉ sử dụng đoạn code của chúng ta (không chỉnh sửa)) thì họ không quan tâm đến việc đối tượng đó được tạo ra như thế nào, họ chỉ cần gọi hàm yêu cầu lấy một đối tượng, nếu có yêu cầu cho việc tạo đối tượng đó (tham số), họ sẽ đưa ra.
Để làm rõ hơn cho vấn đề này, hãy tạo một tình huống thực tế hơn. Ta sẽ coi EmployeeFactory chính là một bộ phận tuyển dụng (Hiring Agency). Bộ phận này có một danh sách những người tương ứng với những kỹ năng gì, và khi công ty cần, họ sẽ đưa cho công ty những người này. Mình sẽ xây dựng lại một lớp HiringAgency mới như sau:


Bộ phận này ban đầu có danh sách những người làm trong nghề. Những người ở đầu danh sách là những người được bộ phận này đánh giá rất cao.
Công ty 8TechBlog đưa ra yêu cầu cho bên bộ phận này tuyển một số người vào công ty.

Tổng cộng họ cần là 2 dev, 1 tester và 1 sale.
Với phương diện là một bộ phận tuyển dụng, chắc chắn họ sẽ đưa ra những nhân viên sáng giá nhất cho công ty. Công việc này là công việc của Hiring Agency (HA), công ty không cần quan tâm điều này. Cái công ty cần chỉ là khi công ty gọi yêu cầu có nhân viên, bên HA phải đưa người qua đây làm nhân viên.
Bây giờ cùng xây dựng tiếp cho lớp HiringAgency nào

Ta có ba hằng số 1, 2, 3 đại diện cho ba nghề developer, tester và sale (Việc nhập job bằng các hằng số thay cho việc nhập chuỗi như ví dụ EmployeeFactory trên sẽ làm cho phía client đỡ phải xác định giá trị chuỗi phải có dạng như thế nào).
(Tại constructor nhớ khởi tạo 3 danh sách nhé. Mình quên :D )
Phương thức getEmployee() sẽ lựa chọn người trong danh sách để trả về (với loại danh sách tùy thuộc vào công việc). list.get(0) tức là chọn người đứng đầu danh sách, là người sáng giá nhất. Và list.remove(0) tức là gạch tên người đó ra khỏi danh sách sau khi chọn.
Sau khi chạy code thì ta nhận được như sau

Phía company đã nhận được 2 dev, 1 tester và 1 sale. Còn ở phía ha thì đã gạch tên những người đưa qua công ty ra khỏi danh sách.
Mẫu này cũng không quá khó các bạn nhỉ!
Sơ đồ thiết kế Factory Pattern về cơ bản sẽ trông như thế này

Product chính là Employee, ConcreteProduct chính là các employee cụ thể (developer, tester, sale). ConcreteCreator chính là cái EmployeeFactory cũng như cái HiringAgency mà chúng ta xây dựng, hàm FactoryMethod() là getEmployee(). Còn class Creator kia là lớp tổng quát (interface) chủ yếu để tổng quát hóa cũng như khi có nhu cầu tạo product với nhiều cách khác nhau thì chúng ta có thể mở rộng thêm từ cái tổng quát đó.
Cảm ơn các bạn đã đón xem! Tuần này có vẻ làm nhanh hơn so với mọi khi, có lẽ là do mẫu này không quá khó so với các mẫu trước.
Trong quá trình viết bài có thể có một số sai sót, mình cũng hơi lo là sẽ làm các bạn hiểu sai, nên các bạn chịu khó tham khảo thêm nhiều bài viết khác nữa nhé =w=”!
Bài viết tuần tới sẽ nói về Adapter Pattern. Mọi người cùng đón xem!
Nội dung bài viết thuộc về Lê Công Diễn. Có sự tham khảo từ kha khá nhiều chỗ, mỗi chỗ một ít nên thôi khỏi ghi :3
Người viết: Lê Công Diễn
Mang đi nhớ ghi nguồn



Nhận xét

Bài đăng phổ biến từ blog này

Deploy project Springboot MIỄN PHÍ sử dụng Render

Ứng dụng Mã hóa bất đối xứng (Asymmetric cryptography) vào Chữ ký số (Digital Signature)

API và HTTP - Một số khái niệm cơ bản cần biết về Web (Phần 2)