使用 factory 关键字标识类的构造函数将会令该构造函数变为工厂构造函数,这将意味着使用该构造函数构造类的实例时并非总是会返回新的实例对象。例如,工厂构造函数可能会从缓存中返回一个实例,或者返回一个子类型的实例。
注意: 在工厂构造函数中无法访问 this。
如果想让抽象类同时可被实例化,可以为其定义 工厂构造函数。
场景1. 避免创建过多的重复实例,如果已创建该实例,则从缓存中拿出来。
class Logger {
final String name;
bool mute = false;
// _cache 变量是库私有的,因为在其名字前面有下划线。
static final Map<String, Logger> _cache =
<String, Logger>{};
factory Logger(String name) {
return _cache.putIfAbsent(
name, () => Logger._internal(name));
}
factory Logger.fromJson(Map<String, Object> json) {
return Logger(json['name'].toString());
}
Logger._internal(this.name);
void log(String msg) {
if (!mute) print(msg);
}
}
场景2. 调用子类的构造函数,这是一种常见的设计模式
abstract class Animal {
String? name;
void getNoise();
factory Animal(String type, String name) {
switch (type) {
case "cat":
return new Cat(name);
case "dog":
return new Dog(name);
default:
throw "The '$type' is not an animal";
}
}
}
class Cat implements Animal {
String? name;
Cat(this.name);
@override
void getNoise() {
print("${this.name}: 喵~");
}
}
class Dog implements Animal {
String? name;
Dog(this.name);
@override
void getNoise() {
print("${this.name}: 旺~");
}
}
void main() {
var cat = new Animal("cat", "花花");
var dog = new Animal("dog", "小黑");
cat.getNoise(); // 花花: 喵~
dog.getNoise(); // 小黑: 旺~
}
场景3. 单利模式
class Singleton {
static final Singleton _singleton = Singleton._internal();
factory Singleton() {
return _singleton;
}
Singleton._internal();
}
void main() {
var s1 = Singleton();
var s2 = Singleton();
print(identical(s1, s2)); // true
}