factory简介
在Dart中,factory关键字用于定义工厂构造函数。factory关键字用于声明一个工厂构造函数。工厂构造函数可以用于创建对象,但与普通构造函数不同,它可以自定义对象的创建过程,并且不一定返回一个新的实例。它与普通的构造函数有以下几个区别:
- factory构造函数的调用可以返回子类型或其它类型的实例。普通构造函数总是返回其包含的类型的实例。
- factory构造函数可以有返回值。普通构造函数的返回值永远是其包含的类型的实例。
- factory构造函数不需要初始化包含类型的所有字段。普通构造函数需要确保所有非空的字段都有值。
使用factory的好处
- 可以根据传入的参数返回其它类型的实例,增加灵活性。
- 不需要全部初始化包含类型的字段,可以决定返回的实例属性,增加灵活性。
- 可以有返回值,不仅限于返回包含类型的实例,增加灵活性。
一般来说,当你的构造函数不完全按照包含类型的定义来初始化实例时,或者可能返回其它类型的实例,那么应该把它定义为factory构造函数。
实例
这里有一个示例可以说明factory构造函数的用法:
class Image {
final String name;
Image(this.name);
}
class ImageCache {
static Map<String, Image> _cache = {};
factory ImageCache.fromName(String name) {
if (_cache.containsKey(name)) {
return _cache[name];
} else {
final image = Image(name);
_cache[name] = image;
return image;
}
}
}
例子说明
这里我们有:
- Image 类表示一个图片,有name字段。
- ImageCache 类表示图片缓存,有一个_cache字段存储所有的图片。
- ImageCache有一个factory构造函数fromName,用来从图片name创建ImageCache。
那么这个构造函数的用法如下:
var image1 = ImageCache.fromName('image1');
var image2 = ImageCache.fromName('image2');
var image3 = ImageCache.fromName('image1');
第一次调用时,会创建一个Image(‘image1’)的实例,存入缓存,并返回。
第二次调用时,会再创建一个Image(‘image2’)的实例,存入缓存,并返回。
但是第三次调用时,会直接从缓存返回第一个Image(‘image1’)的实例。
好处
所以这里使用factory构造函数有几个好处:
- 根据name的不同可以返回Image或ImageCache的实例,增加灵活性。
- 不必要每次调用都创建新的Image实例,可以重用缓存中的实例,优化性能。
- 有返回值Image或ImageCache的实例,而不仅限于ImageCache的实例。
这是一个典型的使用factory构造函数的例子,用来进行实例重用和灵活的返回值。
factory经常被用来创建单例模式
举例说明
import 'package:fluro/fluro.dart';
class AppRouter {
static final AppRouter _instance = AppRouter._internal();
factory AppRouter() {
return _instance;
}
AppRouter._internal();
static FluroRouter router = FluroRouter();
// 添加路由处理方法
void defineRoutes() {
router.define('/home', handler: homeHandler);
// 定义其他路由...
}
// 定义路由处理器
final homeHandler = Handler(
handlerFunc: (BuildContext? context, Map<String, dynamic> params) {
return HomePage();
},
);
}
例子代码说明
例子中,类AppRouter的声明和实例化是同时进行的,
具体来说,AppRouter类的声明中包含一个静态字段_instance,用于存储该类的唯一实例。在声明这个字段时,同时也会通过调用AppRouter._internal()来实例化AppRouter类,并将这个实例赋值给_instance字段。
虽然在类的声明过程中,类的实例化尚未完成,但是由于在声明中使用了AppRouter._internal()来创建实例的方式,因此可以在声明中使用类名AppRouter来引用这个正在创建的实例。
这种方式常用于实现单例模式,通过在类的声明中同时实例化该类,确保只有唯一的实例存在,并且使用静态字段引用这个实例。这样可以确保在整个应用程序中使用同一个实例,并通过类名来访问它。
工程构造函数
工厂构造函数的工作原理如下:
当使用AppRouter()调用工厂构造函数时,实际上是在请求获取一个AppRouter的实例。
在工厂构造函数的实现中,通过返回_instance,返回已经创建的实例,而不是创建一个新的实例。
因此,无论调用多少次AppRouter(),都会返回同一个已经创建的实例,实现了单例的效果。
这种方式可以防止多次创建实例,保证只有一个实例在应用程序中被使用。在这种情况下,工厂构造函数不一定返回一个新的实例,而是返回一个已经存在的实例。
需要注意的是,由于factory关键字的存在,AppRouter()不能直接通过new关键字来实例化,而是通过工厂构造函数来获取实例。