从Flutter范儿的单例来看Dart的构造函数

news2024/11/18 7:52:03

5004a577ec8defdda16fa67c2760de3d.png

点击上方蓝字关注我,知识会给你力量

340fd3e17bfff2683a7a8f4c8e9a36ff.png

单例模式

单例模式应该是设计模式中使用的最广泛的一种设计模式了,在Kotlin中,甚至为它单独创建了一个语法糖——object类,来快速实现单例模式,而在Dart中,并没有像Kotlin这样的语法糖,所以,参考单例的一般实现,我们可以很容易的实现下面这样一个单例。

class Singleton {
  static Singleton? _instance;

  // 私有的命名构造函数
  Singleton._private() {
    // TODO
  }

  static Singleton getInstance() {
    if (_instance == null) {
      _instance = Singleton._private();
    }
    return _instance!;
  }
}

上面的代码与大部分编程语言的代码都差不多,不外乎就是单例的几个特点:

  • 私有构造函数

  • 静态instance访问

在Dart中,变量和函数前面加上「_」就代表私有,但这个私有实际上的含义是「只能在当前文件中访问」,所以,如果在当前文件中,你依然是可以访问这个私有变量或者函数的。另外,由于Dart是单线程模型,所以也不存在线程安全的问题,不用做线程控制。

上面的代码,作为一个Dart初学者来说,是无可厚非的,但是对于老司机来说,明显没有Flutter范儿,所以,我们借助Dart的语法糖,来改造下上面的单例代码。

class Singleton {
  static Singleton? _instance;

  // 私有的命名构造函数
  Singleton._private() {
    // TODO
  }

  static Singleton get instance => _instance ??= Singleton._private();
}

首先,通过「??=」来简化空判断,其次,通过get函数来获取实例,将instance函数变成了instance变量。这样一来,代码简化了不少,而且也更加简单了。

不过,这依然不是最具Flutter范儿的单例写法,在Dart中,它提供了一个factory关键字,与Kotlin中的object关键字,有异曲同工之妙,我们来看看官方推荐的单例写法。

class Singleton {
  static final Singleton _singleton = Singleton._internal();

  factory Singleton() => _singleton;

  Singleton._internal() {
    // TODO
  }
}

�所谓的factory constructor,它的作用是「仅在第一次创建实例,后续都返回相同的实例」,这不就是天然的单例吗,所以,借助factory constructor,我们可以很方便的写出一个Flutter范儿的单例。

构造函数

构造函数是一个类在初始化时,主动调用的函数,在Dart中,有多种不同的构造函数,它们在不同的场景下使用,可以极大的简化我们的代码,同时也让我们的代码更加具有Flutter范儿。

默认构造函数

缺省构造函数不用自己创建,如果一个类没有构造函数,那么它会自动添加一个,它什么都不做。

// Default Constructor
class Test {
  String name = 'xys';
  Test();
}

在构造函数中初始化变量

Dart提供了多种不同的方式在构造函数中未变量赋值,其中最简单的,就是在构造时初始变量。

// Constructor with parameters
class Test {
  String name;
  Test(this.name);
}

其实Test(this.name)实际上就是Test(String name){this.name = name}的简化写法。

同时,构造函数也可以增加方法体,进行一些初始化逻辑。

// Constructor with the initial method
class Test {
  String name;
  Test(this.name) {
    // TODO
  }
}

�当你需要在构造函数初始化时给变量赋值时,可以通过initializer list来实现。

// Constructor with initializer
class Test {
  String name;
  
  Test(name) : name = handleSth(name);
  
  static String handleSth(String e) => e.toUpperCase();
}

initializer list可以初始化多个变量,它们之间可以使用「,」进行分隔,如果有super构造器,那么它一般放在最后。

如果你要override基类的变量,那么可以通过super关键字来覆写。

// Constructor with super()
class Base {
  String id;
  Base(this.id);
}
class Test extends Base {
  String name;
  Test(this.name, String id) : super(id);
}

另外,构造函数中,还支持通过Asserts�来做一些检查。

// Constructor with assertion
class Test {
  String name;
  Test(this.name) : assert(name.length > 3);
}

对于Dart的参数来说,通常我们设置的都是必选参数,就是类似我们上面的这些参数,而在Dart中,还可以设置可选参数。

class Test {
  String name;

  Test(this.name, [int sex = 0]);
}

Test('xys', 1);

或者你觉得可选参数在使用时的语义不太明确,那么你可以使用具名参数。

class Test {
  String name;

  Test(this.name, {int sex = 0});
}

Test('xys', sex: 1);

这样在使用时,语义会更加明确。

私有构造函数

私有构造函数,除了我们前面提到的单例使用场景外,下面这个场景,也使用的很多。

class Utils {
  Utils._();
  static void log(String message) => print(message);
}

通过私有构造函数,我们可以避免使用者创建工具类的实例,而是让使用者直接调用静态函数。

具名构造函数

具名构造函数可以给当前的构造逻辑起一个别名,方便调用者通过语义来进行调用。

// Constructor with this()
class Test {
  String name;
  int sex;
  Test(this.name, this.sex);
  Test.boy(String name) : this(name, 1);
  Test.girl(String name) : this(name, 0);
}

const构造函数

const构造函数在Flutter中使用的非常多,因为一个const构造函数是不可变的,const构造函数在运行时会指向内存空间的同一个对象,从而提高代码执行的效率,所以,在Flutter中,如果一个Widget是可以定义为const的,那就把它定义为const吧。

factory构造函数

factory constructor前面我们已经讲解过了,它可以从另一个构造函数,或者是其它类,返回一个唯一的实例。最常用的场景就是单例的使用,我们来看下它的另一个使用场景,即从缓存中返回唯一实例。

class Test {
  final String name;

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

  Test._(this.name);

  factory Test(name) => _cache[name] ??= Test._(name);
}

factory构造函数与static method的区别

在大部分时间,这两者都是非常类似的,甚至是可以混用的,但是它们之间,还是有一些区别的。

对于factory constructor来说,它不需要命名,也不用指定通用参数,这样可以减少很多模板代码,我们来看下面这个例子。

class ComplexClass<Value, Notifier extends ValueNotifier<Value>> {}

在这个例子中,它包含一个比较复杂的泛型,如果我们要创建一个静态工厂,那么就需要这样:

class ComplexClass<Value, Notifier extends ValueNotifier<Value>> {
  static ComplexClass<Value, Notifier> someFactory<ComplexClass<Value, Notifier extends ValueNotifier<Value>>() {
    // TODO: return a ComplexClass instance
  }
}

我们需要创建很复杂的参数类型,但是使用factory constructor,则可以避免这些模板代码。

class ComplexClass<Value, Notifier extends ValueNotifier<Value>> {
  factory ComplexClass.someFactory() {
    // TODO: return a ComplexClass instance
  }
}

向大家推荐下我的网站 https://www.yuque.com/xuyisheng  点击原文一键直达

专注 Android-Kotlin-Flutter 欢迎大家访问

往期推荐

  • 从源码看Flutter Android端的启动流程

  • Flutter鸿蒙终端一体化—鹊桥相会

  • Flutter鸿蒙终端一体化-珠联璧合

  • Flutter鸿蒙终端一体化-混沌初开

本文原创公众号:群英传,授权转载请联系微信(Tomcat_xu),授权后,请在原创发表24小时后转载。

< END >

作者:徐宜生

更文不易,点个“三连”支持一下👇

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1655804.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

人大金仓数据库报com.kingbase8.util.KSQLException: 致命错误: 用户 “SYSTEM“ Password 认证失败

com.kingbase8.util.KSQLException: 致命错误: 用户 “SYSTEM” Password 认证失败 解决办法&#xff1a; 问题在于用户权限只不足&#xff0c;相关配置文件在一般在 /data/sys hba.conf,修改IPV4 local connections选项中的改为trust。

第1章 信息系统综合知识 1.1 信息的定义和属性

第1章 信息系统综合知识 1.1 信息的定义和属性 1.1.1 信息的基本概念 控制论创始人维纳认为&#xff1a;信息就是信息&#xff0c;既不是物质也不是能量。 信息论的奠基者香农认为&#xff1a;信息就是能够用来消除不确定性的东西。 其他流行说法&#xff1a;信息是事先不…

回归的无分布预测推理

摘要 我们利用保形推理&#xff0c;开发了回归中无分布预测推理的一般框架。所提出的方法允许使用回归函数的任何估计量构建响应变量的预测带。所得的预测带在标准假设下保留了原始估计量的一致性&#xff0c;同时保证了有限样本边际覆盖&#xff0c;即使这些假设不成立。我们…

代码随想录算法训练营第二十一天:树树树

代码随想录算法训练营第二十一天&#xff1a;树树树 ‍ 513.找树左下角的值 力扣题目链接​**&#xff08;打开新窗口&#xff09;** 给定一个二叉树&#xff0c;在树的最后一行找到最左边的值。 示例 1: ​​ 示例 2: ​​ #算法公开课 《代码随想录》算法视频公开课…

Spring底层入门(七)

1、异常处理 在DispatcherServlet中&#xff0c;doDispatch(HttpServletRequest request, HttpServletResponse response) 方法用于进行任务处理&#xff1a; 在捕获到异常后没有立刻进行处理&#xff0c;而是先用一个局部变量dispatchException进行记录&#xff0c;然后统一由…

【GaussTech速递】数据库技术解读之细粒度资源管控

背景 对数据库集群内资源管控与资源隔离一直是企业客户长久以来的诉求。华为云GaussDB作为一款企业级分布式数据库&#xff0c;一直致力于满足企业对大型数据库集群的管理需要。 数据库可以管理的资源有计算资源与存储资源&#xff0c;计算资源包括CPU、内存、IO与网络&#…

FastAPI vs Flask: 选择最适合您的 Python Web 框架

文章目录 1. 简介2. 安装和设置3. 路由和视图4. 自动文档生成5. 数据验证和序列化6. 性能和异步支持结论 在 Python Web 开发领域&#xff0c;FastAPI 和 Flask 是两个备受欢迎的选择。它们都提供了强大的工具和功能&#xff0c;但是在某些方面有所不同。本文将比较 FastAPI 和…

error LNK2001: 无法解析的外部符号 “__declspec(dllimport) public: __cdecl ......

运行程序时&#xff0c;报如上图所示错误&#xff0c;其中一条是&#xff1a; ReflectionProbe.obj : error LNK2001: 无法解析的外部符号 "__declspec(dllimport) public: __cdecl osg::Object::Object(bool)" (__imp_??0ObjectosgQEAA_NZ) 报这个错误一般是因为…

前端Web如何实现将一个 ECharts 动效保存为一张 GIF 动图?

前端Web如何实现将一个 ECharts 动效保存为一张 GIF 动图&#xff1f; 博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;…

[Cpp]类和对象 | 实现日期类

标题&#xff1a;[Cpp]类和对象 | 实现日期类 水墨不写bug 正文开始&#xff1a; 类和对象是Cpp面向对象编程区别于C的面向过程编程的重要的一部分&#xff0c;因此打好坚实的类和对象的基础对于深入学习Cpp语言是比较明智的。 本文通过实现简单的日期类来加深对类和对象的理解…

【算法】-- 二分查找详注

引入 二分查找&#xff0c;也称为折半查找&#xff1b;首先&#xff0c;二分查找是一种基于有序数组中查找特定元素的算法&#xff0c;所以它会因为数组的一些特性而受限。它的工作原理是不断将要查找的区间分成两部分&#xff0c;然后确定目标值可能存在的区间&#xff0c;直…

VUE 或 Js封装通用闭包循环滚动函数

1、vue3 闭包滚动函数的使用 js 调用也基本雷同 // 滚动Tab组件const scoreTabRef ref()// 滚动的选项const scrollOption ref({// 滚动的Dom元素scrollDom: null,// 滚动的时间间隔scrollInterval: 1500,// 滚动的距离scrollSep: 100,// 滚动历时时间scrollDuration: 10…

视频汇聚边缘网关EasyCVR硬件设备无法访问域名,解析失败该如何处理?

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。视频汇聚融合管理平台EasyCVR既具备传统安防视…

240多道!Go开发岗位面试题合集(含答案)

随着今年互联网寒潮环境的影响&#xff0c;找工作的人也将达到顶峰&#xff0c;今天给大家分享一份《Go开发工程师超高频面试真题》&#xff0c;一共有240多道面试真题&#xff0c;希望能够帮助大家在面试中&#xff0c;少走一些弯路、更快拿到offer&#xff01; 内容展示 GO 基…

uniapp0基础编写安卓原生插件之编写安卓页面在uniapp上显示(摄像头调用)

前言 如果你对安卓插件开发部分不熟悉你可以先看uniapp0基础编写安卓原生插件和调用第三方jar包和编写语音播报插件之零基础编写安卓插件 效果 开始 dcloud_uniplugins.json {"nativePlugins": [{"hooksClass": "","plugins": [{&…

信奥一本通:1103:陶陶摘苹果

#include <iostream> using namespace std; int a[101]; int main(){int n 10;//题目要求输十个数 for(int i 1;i < 10; i){cin >> a[i];//赋值到数组 }int c;cin >> c;//要求的值 int cnt 0;//计数 for(int i 1; i < n; i){//循环比较是否小于&am…

试用NXP官方的UDS bootloader

文章目录 1.前言2.资料获取2.1 MCU例程 2.2 开发环境2.3 上位机2.4 硬件 3.工程修改3.1 boot工程修改 3.2 app工程修改4.测试情况5.例程分享 1.前言 最近很多客户在开发S32K系列MCU时咨询是否可以提供基于UDS协议的bootloader。本文以S32K144为例&#xff0c;介绍如何使用NXP官…

Parallels Desktop 19 for Mac v19.3.0.54924中文破解版

Parallels Desktop 19 for Mac v19.3.0.54924中文破解版是一款强大的虚拟机软件&#xff0c;支持多操作系统&#xff0c;提供卓越的虚拟化技术&#xff0c;确保流畅稳定的运行。新增特色功能如共享打印、TouchID集成等&#xff0c;提供便捷高效的虚拟机体验。界面美观现代&…

window golang 升级版本

执行go tidy&#xff0c;发现执行不了&#xff0c;得升级一下版本了 进入官网&#xff0c;并选择合适的系统以及版本。https://go.dev/dl/ 这台电脑是windows&#xff0c;我本人比较喜欢下载zip自己解压。 解压&#xff0c;这里我选择直接覆盖原文件&#xff0c;需要保留原版…

即将开幕,邀您共赴创新之旅“2024上海国际消费者科技及创新展览会”

备受期待的2024上海国际消费者科技及创新展览会&#xff08;以下简称“CTIS”&#xff09;即将于6月13日至15日亮相上海新国际博览中心N1-N3馆。 2024上海国际消费者科技及创新展览会总面积达40,000平方米&#xff0c;涵盖600余家展商&#xff0c;预计吸引40,000多位观众莅临现…