Hàm khởi tạo nhà máy
Thuộc phần Lập trình hướng đối tượng trong hành trình Dart của Coddy. Bài học 14 trên 110.
Hàm khởi tạo factory là một hàm khởi tạo đặc biệt, không phải lúc nào cũng tạo ra một instance mới. Khác với các hàm khởi tạo thông thường, hàm khởi tạo factory có thể trả về một instance đã có, một kiểu con hoặc thậm chí là null (nếu có thể nhận giá trị null). Bạn khai báo hàm này bằng từ khóa factory.
class Logger {
static final Logger _instance = Logger._internal();
// Hàm khởi tạo (constructor) có tên riêng tư
Logger._internal();
// Hàm khởi tạo factory
factory Logger() {
return _instance;
}
}
Logger log1 = Logger();
Logger log2 = Logger();
print(identical(log1, log2)); // trueTrong ví dụ này, hàm khởi tạo factory luôn trả về cùng một instance. Dù bạn gọi Logger() bao nhiêu lần, bạn vẫn nhận được cùng một đối tượng. Mẫu này thường được dùng để triển khai singleton.
Hàm khởi tạo factory khác với hàm khởi tạo thông thường ở một điểm quan trọng: chúng không thể truy cập this vì có thể chúng không tạo instance mới nào. Thay vào đó, chúng phải trả về một đối tượng một cách tường minh:
class Shape {
factory Shape(String type) {
if (type == 'circle') return Circle();
if (type == 'square') return Square();
return Rectangle();
}
}
class Circle extends Shape { Circle() : super._(); }
class Square extends Shape { Square() : super._(); }
class Rectangle extends Shape { Rectangle() : super._(); }Hàm khởi tạo factory rất hữu ích khi bạn cần kiểm soát việc tạo instance, chẳng hạn như trả về các đối tượng đã lưu trong bộ nhớ đệm, triển khai nhóm đối tượng hoặc quyết định kiểu con nào cần khởi tạo dựa trên các tham số đầu vào.
Thử thách
DễHãy xây dựng một hệ thống thông báo dùng hàm khởi tạo factory để tạo các loại thông báo khác nhau dựa trên một chuỗi đầu vào đơn giản.
Bạn sẽ tạo hai tệp để sắp xếp code:
notification.dart: Định nghĩa lớpNotificationlàm lớp cơ sở cho mọi loại thông báo. Lớp này cần có:- Một trường
String message - Một hàm khởi tạo có tên riêng tư
Notification._internalđể khởi tạo message - Một hàm khởi tạo factory
Notification(String type, String message)trả về các kiểu thông báo con khác nhau dựa trên tham sốtype:- Nếu type là
'email', hãy trả về mộtEmailNotification - Nếu type là
'sms', hãy trả về mộtSMSNotification - Nếu không, hãy trả về một
PushNotification
- Nếu type là
- Một phương thức
send()in raSending: [message]
- Một trường
Trong cùng tệp, hãy tạo ba lớp con kế thừa từ Notification:
EmailNotification: Ghi đèsend()để in raEmail: [message]SMSNotification: Ghi đèsend()để in raSMS: [message]PushNotification: Ghi đèsend()để in raPush: [message]
Mỗi lớp con cần có một hàm khởi tạo nhận message và truyền giá trị này cho lớp cha bằng super._internal(message).
main.dart: Nhập lớp thông báo và tạo ba thông báo bằng hàm khởi tạo factory:- Một thông báo email với message
'Welcome!' - Một thông báo SMS với message
'Your code is 1234' - Một thông báo push với message
'New update available'
send()cho từng thông báo theo thứ tự trên.- Một thông báo email với message
Đầu ra dự kiến:
Email: Welcome!
SMS: Your code is 1234
Push: New update availableTự làm thử
import 'notification.dart';
void main() {
// TODO: Tạo thông báo email với nội dung 'Welcome!'
// TODO: Tạo thông báo SMS với nội dung 'Your code is 1234'
// TODO: Tạo thông báo đẩy với nội dung 'New update available'
// TODO: Gọi send() trên từng thông báo theo đúng thứ tự
}
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
1Nền tảng về lập trình hướng đối tượng
Tệp bên ngoàiThư viện và câu lệnh importGiới thiệu về lập trình hướng đối tượngLớp và đối tượngTừ khóa thisPhương thứcBiến thể hiệnKiến thức cơ bản về hàm khởi tạoÔn tập: Máy tính đơn giản4An toàn với giá trị null
Giới thiệu về an toàn với giá trị nullCó thể null và không thể nullToán tử ? và !Từ khóa late và an toàn với giá trị nullToán tử xử lý nullAn toàn với giá trị null trong lớpÔn tập: hệ thống hồ sơ người dùng7Lớp trừu tượng và interface
Lớp trừu tượngPhương thức trừu tượngInterface trong DartInterface ngầm địnhTriển khai và kế thừaNhiều interfaceÔn tập: Máy tính hình10Bộ sưu tập và kiểu tổng quát
Tổng quan về List, Set và MapBộ sưu tập an toàn về kiểuLớp tổng quátPhương thức tổng quátRàng buộc kiểu tổng quátIterable và IteratorÔn tập: Lưu trữ tổng quát2Hàm khởi tạo trong Dart
Hàm khởi tạo mặc địnhHàm khởi tạo có tênDanh sách khởi tạoHàm khởi tạo hằng sốHàm khởi tạo nhà máyHàm khởi tạo chuyển hướngÔn tập: Trình tạo hình dạng5Đóng gói
Thành viên công khai và riêng tưQuy ước tiền tố _Tính riêng tư ở cấp thư việnTìm hiểu sâu về getter và setterChe giấu thông tinÔn tập: hồ sơ học sinh8Mixin
Giới thiệu về MixinTạo MixinSử dụng nhiều MixinTừ khóa on trong MixinMixin và kế thừaMixin và giao diệnÔn tập: hệ thống động vật3Thuộc tính của lớp
Thành viên instance và thành viên tĩnhTrường final và constBiến latePhương thức và trường tĩnhGetter và setterÔn tập: trình quản lý tài khoản ngân hàng6Kế thừa
Kế thừa cơ bảnTừ khóa superGhi đè phương thứcChú thích @overrideTừ khóa lớp finalHàm khởi tạo và kế thừaÔn tập: phân cấp nhân viên9Đa hình
Khái niệm cơ bản về đa hìnhĐa hình qua giao diệnKiểm tra kiểu lúc chạyToán tử is và asTừ khóa hiệp biếnÔn tập: Bộ xử lý thanh toánTự luyện tập: Trình biên dịch Dart online