Mẫu Factory
Thuộc phần Lập trình hướng đối tượng trong hành trình C của Coddy. Bài học 55 trên 61.
Mẫu Factory tập trung việc tạo đối tượng vào một hàm duy nhất. Thay vì rải malloc và code khởi tạo khắp chương trình, bạn gọi một hàm để quyết định cần tạo gì và trả về một đối tượng sẵn sàng sử dụng.
Mẫu này đặc biệt hữu ích khi kết hợp với tính đa hình. Một hàm tạo có thể trả về các kiểu cụ thể khác nhau thông qua một con trỏ cơ sở chung, che giấu chi tiết khởi tạo với bên gọi. Bên gọi chỉ cần yêu cầu “một hình dạng”, còn hàm tạo sẽ quyết định tạo hình tròn, hình chữ nhật hay hình dạng khác.
Đây là cách triển khai factory điển hình:
typedef enum {
SHAPE_CIRCLE,
SHAPE_RECTANGLE
} ShapeType;
Shape* create_shape(ShapeType type) {
switch (type) {
case SHAPE_CIRCLE:
return (Shape*)create_circle(5.0);
case SHAPE_RECTANGLE:
return (Shape*)create_rectangle(4.0, 3.0);
default:
return NULL;
}
}Hàm factory nhận một mã định danh (thường là enum) và dùng câu lệnh switch để xác định cần gọi hàm khởi tạo nào. Hàm trả về một Shape* bất kể kiểu thực tế được tạo ra là gì. Bên gọi không cần biết về Circle hay Rectangle. Bên gọi chỉ cần làm việc với kiểu cơ sở:
Shape* s = create_shape(SHAPE_CIRCLE);
s->draw(s); // lời gọi đa hình
free_shape(s);Mẫu này giúp bạn dễ dàng thêm kiểu mới: chỉ cần thêm một giá trị enum mới và một nhánh case mới trong hàm factory. Phần còn lại của code vẫn giữ nguyên.
Thử thách
DễHãy xây dựng một nhà máy thú cưng: một hệ thống tạo ra nhiều loại thú cưng thông qua một hàm nhà máy (factory function). Thay vì rải rác logic tạo thú cưng khắp đoạn code, bạn sẽ tập trung logic đó vào một nơi để quyết định cần tạo loại thú cưng nào dựa trên mã định danh đầu vào.
Bạn sẽ sắp xếp đoạn code trong ba tệp:
pet.h: Định nghĩa một enumPetTypevới các giá trịPET_DOG,PET_CATvàPET_BIRD. Tạo một cấu trúcPetcơ sở chứa con trỏ hàm chospeak(hàm này nhận mộtconst Pet*và không trả về giá trị nào). Khai báo hàm nhà máycreate_petnhận mộtPetTypevà trả về mộtPet*, cùng với hàmfree_petđể giải phóng bộ nhớ.pet.c: Định nghĩa ba cấu trúc thú cưng cụ thể làDog,CatvàBird, mỗi cấu trúc đều cóPetlàm thành viên đầu tiên. Cài đặt một hàm phát tiếng kêu cho mỗi loại:- Chó in ra:
Woof! - Mèo in ra:
Meow! - Chim in ra:
Tweet!
create_pet: dùng câu lệnh switch vớiPetTypeđể gọi hàm khởi tạo thích hợp và trả về kết quả dưới dạngPet*. Với các kiểu không hợp lệ, trả vềNULL. Cài đặtfree_petđể giải phóng bộ nhớ đã cấp phát.- Chó in ra:
main.c: Đọc một số nguyên biểu thị loại thú cưng (0 là chó, 1 là mèo, 2 là chim). Dùng hàm nhà máy để tạo thú cưng phù hợp, gọi hàmspeaktheo cách đa hình thông qua con trỏPet*cơ sở, rồi giải phóng thú cưng.
Chương trình của bạn sẽ nhận một đầu vào: số nguyên cho biết cần tạo loại thú cưng nào.
Đầu ra mẫu khi đầu vào là 0:
Woof!Đầu ra mẫu khi đầu vào là 1:
Meow!Đầu ra mẫu khi đầu vào là 2:
Tweet!Điểm hay của mẫu nhà máy là main.c không cần biết về các cấu trúc Dog, Cat hay Bird. Đoạn code chỉ làm việc với kiểu Pet cơ sở. Nếu sau này thêm một loại thú cưng mới, bạn chỉ cần thêm một giá trị enum và một nhánh case mới trong hàm nhà máy, mà không cần thay đổi bất kỳ đoạn code nào đang sử dụng thú cưng.
Tự làm thử
#include <stdio.h>
#include "pet.h"
int main(void) {
int type;
scanf("%d", &type);
// TODO: Dùng factory để tạo thú cưng phù hợp
// Gợi ý: Ép kiểu int sang PetType
// TODO: Gọi hàm (function) speak theo cách đa hình thông qua con trỏ Pet*
// TODO: Giải phóng bộ nhớ của thú cưng
return 0;
}
Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Lập trình hướng đối tượng
1Kiến thức cơ bản về lập trình mô-đun
Tệp tiêu đềInclude guardTệp mã nguồnHàm staticÔn tập: Máy tính mô-đun4Tính đóng gói
Khái niệm con trỏ mờĐịnh nghĩa struct mờHàm truy xuất và hàm gánKiểm tra tính hợp lệ trong hàm gánÔn tập: Hộp bí mật2Đối tượng và phương thức
Struct dưới dạng đối tượngCon trỏ 'Self'Tính đúng đắn của constCon trỏ và giá trịPhương thức hỗ trợÔn tập: trình quản lý Point5Dự án: Tài khoản ngân hàng đơn giản
Thiết lập dự ánTriển khai tài khoản3Vòng đời đối tượng
Mẫu hàm khởi tạoMẫu hàm hủyKhởi tạo trên ngăn xếpSao chép sâuÔn tập: lớp bao bọc chuỗi6Kế thừa bằng cách kết hợp
Nhúng structQuy tắc thành viên đầu tiênTruy cập thành viên lớp chaUpcastingÔn tập: hệ phân cấp hình dạngTự luyện tập: Trình biên dịch C online