工厂模式
本课属于 Coddy Dart 学习旅程的“面向对象编程”单元。第 91 课,共 110 课。
工厂模式将对象的创建交给单独的方法或类,让你无需指定对象的确切类即可创建对象。这与之前学过的工厂构造函数不同。工厂模式是一种设计方法,它将创建逻辑集中起来,并可根据输入返回不同类型。
考虑这样一种情况:你需要创建不同类型的通知。由工厂来决定实例化哪个类,而不是由客户端决定:
abstract class Notification {
void send(String message);
}
class EmailNotification implements Notification {
@override
void send(String message) => print('Email: $message');
}
class SMSNotification implements Notification {
@override
void send(String message) => print('SMS: $message');
}
class NotificationFactory {
static Notification create(String type) {
switch (type) {
case 'email':
return EmailNotification();
case 'sms':
return SMSNotification();
default:
return EmailNotification();
}
}
}
void main() {
var notification = NotificationFactory.create('sms');
notification.send('Hello!'); // SMS: Hello!
}客户端代码不需要了解 EmailNotification 或 SMSNotification,它只需向工厂请求特定类型的通知。这样一来,添加新的通知类型就很容易:你只需修改工厂,而不必修改每个创建通知的地方。
当对象的创建涉及复杂逻辑、你想对客户端隐藏实现类,或要创建的确切类型取决于运行时条件时,使用工厂模式。
挑战
简单让我们使用工厂模式来构建一个文档生成器!你将创建一个系统,通过集中式工厂生成不同类型的文档(报告、发票和信件),这样客户端代码就不需要了解具体的文档类。
你将把代码整理到两个文件中:
document_factory.dart:在这里创建文档系统:- 创建一个抽象类
Document,其中包含一个方法generate(String content),该方法返回一个String - 创建三个实现
Document的具体类:Report:它的generate方法返回=== REPORT ===\n[content]\n=============Invoice:它的generate方法返回INVOICE\n--------\n[content]\nTotal DueLetter:它的generate方法返回Dear Reader,\n[content]\nSincerely
- 创建一个
DocumentFactory类,其中包含一个静态方法create(String type),根据类型字符串返回相应的Document:"report"、"invoice"或"letter"。对于任何未知类型,默认返回一个Letter
- 创建一个抽象类
main.dart:导入文档工厂,并演示工厂如何创建不同类型的文档,而客户端不需要了解具体类:- 使用工厂创建一份报告,并打印使用内容
Sales increased by 25%生成的结果 - 打印一个空行
- 使用工厂创建一张发票,并打印使用内容
Widget x3 - $150生成的结果 - 打印一个空行
- 使用工厂创建一封信,并打印使用内容
Thank you for your order生成的结果
- 使用工厂创建一份报告,并打印使用内容
注意,主文件只与工厂和抽象的 Document 类型交互,它从不直接创建 Report、Invoice 或 Letter 对象!
预期输出:
=== REPORT ===
Sales increased by 25%
=============
INVOICE
--------
Widget x3 - $150
Total Due
Dear Reader,
Thank you for your order
Sincerely亲手试试
import 'document_factory.dart';
void main() {
// TODO: 使用 DocumentFactory.create() 创建一份报告
// 然后打印用内容 "Sales increased by 25%" 生成的结果
// TODO: 打印一个空行
// TODO: 使用 DocumentFactory.create() 创建一张发票
// 然后打印用内容 "Widget x3 - \$150" 生成的结果
// TODO: 打印一个空行
// TODO: 使用 DocumentFactory.create() 创建一封信
// 然后打印用内容 "Thank you for your order" 生成的结果
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Dart 在线编译器