Menu
CoddyTech

工厂构造函数

本课属于 Coddy Dart 学习旅程的“面向对象编程”单元。第 14 课,共 110 课。

工厂构造函数是一种特殊的构造函数,不一定总会创建新实例。与普通构造函数不同,工厂构造函数可以返回已有实例、子类型,甚至 null(如果允许为空)。你可以使用 factory 关键字声明它。

class Logger {
  static final Logger _instance = Logger._internal();
  
  // 私有命名构造函数
  Logger._internal();
  
  // 工厂构造函数
  factory Logger() {
    return _instance;
  }
}

Logger log1 = Logger();
Logger log2 = Logger();
print(identical(log1, log2)); // true

在这个示例中,工厂构造函数总是返回同一个实例。无论你调用 Logger() 多少次,得到的都是同一个对象。这种模式通常用于实现单例。

工厂构造函数与普通构造函数的一个关键区别是:它们无法访问 this,因为它们可能根本不会创建新实例。相反,它们必须显式返回一个对象:

class Shape {
  factory Shape(String type) {
    if (type == 'circle') return Circle();
    if (type == 'square') return Square();
    return Rectangle();
  }
}

class Circle extends Shape { Circle() : super._(); }
class Square extends Shape { Square() : super._(); }
class Rectangle extends Shape { Rectangle() : super._(); }

当你需要控制实例的创建方式时,工厂构造函数会很有用,例如返回缓存对象、实现对象池,或根据输入参数决定实例化哪个子类型。

challenge icon

挑战

简单

我们来构建一个通知系统,根据简单的字符串输入,使用工厂构造函数创建不同类型的通知。

你将创建两个文件来组织代码:

  • notification.dart:定义一个 Notification 类,作为所有通知类型的基类。这个类应包含:
    • 一个 String message 字段
    • 一个私有命名构造函数 Notification._internal,用于初始化 message
    • 一个工厂构造函数 Notification(String type, String message),根据 type 参数返回不同的通知子类:
      • 如果 type 是 'email',则返回一个 EmailNotification
      • 如果 type 是 'sms',则返回一个 SMSNotification
      • 否则,返回一个 PushNotification
    • 一个 send() 方法,用于打印 Sending: [message]

在同一个文件中,创建三个继承 Notification 的子类:

  • EmailNotification:重写 send(),打印 Email: [message]
  • SMSNotification:重写 send(),打印 SMS: [message]
  • PushNotification:重写 send(),打印 Push: [message]

每个子类都需要一个接收 message 的构造函数,并通过 super._internal(message) 将它传给父类。

  • main.dart:导入通知类,并使用工厂构造函数创建三个通知:
    • 创建一条消息为 'Welcome!' 的电子邮件通知
    • 创建一条消息为 'Your code is 1234' 的 SMS 通知
    • 创建一条消息为 'New update available' 的推送通知
    按照上面列出的顺序,对每个通知调用 send()。

预期输出:

Email: Welcome!
SMS: Your code is 1234
Push: New update available

亲手试试

import 'notification.dart';

void main() {
  // TODO:创建一条电子邮件通知,消息内容为 'Welcome!'
  
  // TODO:创建一条短信通知,消息内容为 'Your code is 1234'
  
  // TODO:创建一条推送通知,消息内容为 'New update available'
  
  // TODO:依次对每条通知调用 send()
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: Dart 在线编译器