[Dart] Factory Constructor là gì?

[Dart] Factory Constructor là gì?

Factory Constructor là một loại constructor đặc biệt trong Dart. Thay vì luôn luôn tạo ra một thể hiện (instance) mới của lớp khi nó được gọi, một factory constructor có khả năng:

  • Trả về một thể hiện đã có từ trước.
  • Trả về một thể hiện của một lớp con (subclass) khác.
  • Trả về null.

Nói một cách đơn giản, factory constructor cho phép bạn kiểm soát logic tạo đối tượng một cách linh hoạt hơn so với constructor thông thường. Nó không bị giới hạn trong việc chỉ tạo và trả về một thể hiện mới của chính lớp đó.

Cú pháp:

Để định nghĩa một factory constructor, bạn sử dụng từ khóa factory trước tên constructor:

class MyClass {
  String? name;

  // Constructor thông thường
  MyClass(this.name);

  // Factory constructor
  factory MyClass.createSpecial(String specialName) {
    if (specialName == "special") {
      return MySpecialClass(specialName); // Trả về thể hiện của lớp con
    } else {
      return MyClass(specialName); // Trả về thể hiện của chính lớp MyClass
    }
  }

  static final _cache = <String, MyClass>{};

  factory MyClass.getFromCache(String key) {
    if (_cache.containsKey(key)) {
      return _cache[key]!; // Trả về thể hiện từ cache
    } else {
      final instance = MyClass("Cached: $key");
      _cache[key] = instance;
      return instance; // Tạo mới và lưu vào cache trước khi trả về
    }
  }
}

class MySpecialClass extends MyClass {
  MySpecialClass(String name) : super(name);

  void doSpecialThing() {
    print("$name is doing something special!");
  }
}

void main() {
  var obj1 = MyClass("Regular");
  var obj2 = MyClass.createSpecial("special");
  var obj3 = MyClass.createSpecial("another");
  var obj4 = MyClass.getFromCache("key1");
  var obj5 = MyClass.getFromCache("key1"); // Sẽ trả về cùng thể hiện với obj4

  print(obj1.name); // Output: Regular
  if (obj2 is MySpecialClass) {
    obj2.doSpecialThing(); // Output: special is doing something special!
  }
  print(obj3.name); // Output: another
  print(obj4.name); // Output: Cached: key1
  print(obj5.name); // Output: Cached: key1
  print(identical(obj4, obj5)); // Output: true (cùng một đối tượng trong cache)
}
Dart

Khi nào nên sử dụng Factory Constructor?

  1. Factory constructor rất hữu ích trong các tình huống sau:
  • Quản lý Singleton: Khi bạn muốn đảm bảo rằng chỉ có một thể hiện duy nhất của một lớp tồn tại trong suốt vòng đời của ứng dụng. Factory constructor có thể kiểm tra xem thể hiện đã được tạo chưa và trả về thể hiện đã có nếu có.
class Singleton {
  static Singleton? _instance;

  Singleton._internal(); // Private named constructor

  factory Singleton() {
    _instance ??= Singleton._internal();
    return _instance!;
  }

  void doSomething() {
    print("Singleton instance is doing something.");
  }
}

void main() {
  var s1 = Singleton();
  var s2 = Singleton();
  print(identical(s1, s2)); // Output: true (cùng một đối tượng)
  s1.doSomething();
}
Dart

2. Tạo đối tượng của lớp con: Dựa trên một số điều kiện hoặc dữ liệu đầu vào, factory constructor có thể quyết định trả về một thể hiện của một lớp con cụ thể thay vì chính lớp đó.

abstract class Shape {
  factory Shape(String type) {
    if (type == 'circle') {
      return Circle();
    } else if (type == 'square') {
      return Square();
    } else {
      throw ArgumentError('Unknown shape type: $type');
    }
  }

  void draw();
}

class Circle implements Shape {
  @override
  void draw() {
    print("Drawing a circle.");
  }
}

class Square implements Shape {
  @override
  void draw() {
    print("Drawing a square.");
  }
}

void main() {
  var circle = Shape('circle');
  circle.draw(); // Output: Drawing a circle.

  var square = Shape('square');
  square.draw(); // Output: Drawing a square.
}
Dart

3. Sử dụng Cache: Factory constructor có thể quản lý một cache các thể hiện đã được tạo và trả về thể hiện đã được cache nếu có yêu cầu cho cùng một trạng thái hoặc khóa.

4. Khởi tạo phức tạp: Trong một số trường hợp, logic khởi tạo một đối tượng có thể rất phức tạp. Factory constructor cho phép bạn chứa logic này bên trong hàm và trả về thể hiện cuối cùng.

Điểm khác biệt chính với Constructor thông thường:

  • Constructor thông thường phải luôn tạo và trả về một thể hiện mới của lớp mà nó thuộc về (hoặc ném ra một lỗi).
  • Factory constructor có sự linh hoạt trong việc trả về các thể hiện đã có, thể hiện của lớp con, hoặc thậm chí null.

Tóm lại, Factory Constructor là một công cụ mạnh mẽ trong Dart để kiểm soát quá trình tạo đối tượng, đặc biệt hữu ích khi bạn cần quản lý duy nhất thể hiện, tạo đối tượng dựa trên điều kiện, hoặc sử dụng cơ chế caching.

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *