Dart中的factory关键字用法

本文介绍了Dart中的factory构造函数,它允许自定义对象创建过程,可以提高灵活性,例如在ImageCache示例中实现缓存重用。此外,factory构造函数常用于创建单例模式,如AppRouter类的实现,确保整个应用中只有一个实例。
摘要由CSDN通过智能技术生成

请添加图片描述

factory简介

在Dart中,factory关键字用于定义工厂构造函数。factory关键字用于声明一个工厂构造函数。工厂构造函数可以用于创建对象,但与普通构造函数不同,它可以自定义对象的创建过程,并且不一定返回一个新的实例。它与普通的构造函数有以下几个区别:

  1. factory构造函数的调用可以返回子类型或其它类型的实例。普通构造函数总是返回其包含的类型的实例。
  2. factory构造函数可以有返回值。普通构造函数的返回值永远是其包含的类型的实例。
  3. factory构造函数不需要初始化包含类型的所有字段。普通构造函数需要确保所有非空的字段都有值。

使用factory的好处

  1. 可以根据传入的参数返回其它类型的实例,增加灵活性。
  2. 不需要全部初始化包含类型的字段,可以决定返回的实例属性,增加灵活性。
  3. 可以有返回值,不仅限于返回包含类型的实例,增加灵活性。
    一般来说,当你的构造函数不完全按照包含类型的定义来初始化实例时,或者可能返回其它类型的实例,那么应该把它定义为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构造函数有几个好处:

  1. 根据name的不同可以返回Image或ImageCache的实例,增加灵活性。
  2. 不必要每次调用都创建新的Image实例,可以重用缓存中的实例,优化性能。
  3. 有返回值Image或ImageCache的实例,而不仅限于ImageCache的实例。
    这是一个典型的使用factory构造函数的例子,用来进行实例重用和灵活的返回值。
    image.png

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关键字来实例化,而是通过工厂构造函数来获取实例。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值