中介者模式(Mediator Pattern)是一种行为设计模式,其主要目的是降低多个类之间的通信复杂性。这种模式提供了一个中介类,该类通常处理所有类之间的通信,这样各类不需要互相引用,从而使其耦合性降低,同时提高了代码的可读性和可维护性。
中介者模式的主要参与者有:
- 中介者(Mediator): 定义了一个接口,用于与各同事对象通信。
- 具体中介者(Concrete Mediator): 实现中介者接口并协调各同事对象。
- 同事类(Colleague): 定义了各同事类的接口。
- 具体同事类(Concrete Colleague): 实现同事类的接口,它需要知道中介者对象,以便与其他同事通信。
适用场景:
- 系统中对象之间存在大量的紧密耦合。
- 想定制一个分布在多个类中的行为,但又不想生成太多的子类。
下面让我们一起来看一下,如何在Flutter中使用中介者模式(Mediator Pattern)来简化开发。
场景一:聊天应用
一个聊天室,每个用户都可以发送消息,而不需要知道其他用户的存在。聊天室作为中介者,负责接收和广播消息。
- 创建一个中介者接口
ChatMediator,定义了同事对象之间的通信协议。 - 具体的中介者
ChatRoom实现了消息的广播机制。 - 每个用户作为同事对象
ChatUser,知道如何发送消息并接收来自中介者的消息。
// Mediator
abstract class ChatMediator {
void sendMessage(String msg, ChatUser user);
void addUser(ChatUser user);
}
// ConcreteMediator
class ChatRoom implements ChatMediator {
List<ChatUser> users = [];
@override
void addUser(ChatUser user) {
users.add(user);
}
@override
void sendMessage(String msg, ChatUser user) {
for (var u in users) {
// Message should not be relayed back to the sender
if (u != user) {
u.receive(msg);
}
}
}
}
// Colleague
abstract class ChatUser {
void send(String message);
void receive(String message);
}
// ConcreteColleague
class ChatMember implements ChatUser {
String name;
ChatMediator? chatMediator;
ChatMember(this.name, this.chatMediator) {
chatMediator?.addUser(this);
}
@override
void send(String message) {
chatMediator?.sendMessage(message, this);
}
@override
void receive(String message) {
print('$name received: $message');
}
}
class ChatApp extends StatefulWidget {
@override
State<StatefulWidget> createState() => ChatAppState();
}
class ChatAppState extends State<ChatApp> {
ChatMediator? mediator;
ChatUser? john;
ChatUser? jane;
@override
void initState() {
super.initState();
mediator = ChatRoom();
john = ChatMember("John", mediator);
jane = ChatMember("Jane", mediator);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Mediator Pattern in Chat')),
body: Center(
child: Column(
children: [
ElevatedButton(
onPressed: () => john?.send("Hi Jane!"),
child: const Text('John sends message'),
),
ElevatedButton(
onPressed: () => jane?.send("Hi John! How are you?"),
child: const Text('Jane sends message'),
),
],
),
),
),
);
}
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChatApp();
}
}
void main() => runApp(MyApp());
ChatMediator是中介者接口,定义了同事对象之间的通信协议。ChatRoom是具体的中介者,负责将消息从一个用户传递给其他所有用户。ChatUser是同事类接口,定义了用户需要实现的方法。ChatMember是具体的同事类,每个用户都是一个ChatMember的实例。
通过按下按钮,模拟了John和Jane发送消息的场景。
场景二:注册表单
一个注册表单,其中有多个字段如用户名、密码和电子邮件。当用户输入数据时,每个字段都会进行验证。我们可以使用中介者模式来协调这些验证,当所有字段都有效时,激活提交按钮。
FormMediator中介者负责整个表单的验证。FormField每个字段作为同事对象,知道如何验证自己并通知中介者进行整体验证。- 当所有的字段都通过验证时,中介者会激活提交按钮。
// Mediator
abstract class FormMediator {
void validateForm();
void addColleague(FormFieldColleague colleague);
}
// ConcreteMediator
class RegisterFormMediator implements FormMediator {
final List<FormFieldColleague> colleagues = [];
final Function(bool) onFormValidationChanged;
RegisterFormMediator(this.onFormValidationChanged);
@override
void addColleague(FormFieldColleague colleague) {
colleagues.add(colleague);
}
@override
void validateForm() {
bool isFormValid = colleagues.every((colleague) => colleague.isValid);
onFormValidationChanged(isFormValid);
}
}
// Colleague
abstract class FormFieldColleague {
bool get isValid;
void onFieldChanged();
}
// ConcreteColleague
class FormField extends StatefulWidget {
final FormMediator mediator;
final TextInputType keyboardType;
final String labelText;
final String? Function(String?) validator;
FormField({
required this.mediator,
required this.labelText,
this.keyboardType = TextInputType.text,
required this.validator,
});
@override
_FormFieldState createState() => _FormFieldState();
}
class _FormFieldState extends State<FormField> implements FormFieldColleague {
final TextEditingController _controller = TextEditingController();
bool _isValid = false;
@override
bool get isValid => _isValid;
@override
void initState() {
super.initState();
widget.mediator.addColleague(this);
_controller.addListener(onFieldChanged);
}
@override
void onFieldChanged() {
setState(() {
_isValid = widget.validator(_controller.text) == null;
widget.mediator.validateForm();
});
}
@override
Widget build(BuildContext context) {
return TextFormField(
controller: _controller,
keyboardType: widget.keyboardType,
decoration: InputDecoration(labelText: widget.labelText),
validator: widget.validator,
);
}
}
class RegistrationForm extends StatefulWidget {
@override
_RegistrationFormState createState() => _RegistrationFormState();
}
class _RegistrationFormState extends State<RegistrationForm> {
bool _isFormValid = false;
late final FormMediator mediator;
@override
void initState() {
super.initState();
mediator = RegisterFormMediator((isValid) {
setState(() {
_isFormValid = isValid;
});
});
}
String? _validateNotEmpty(String? value) {
return value?.isEmpty == true ? 'Field is required' : null;
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Registration Form with Mediator')),
body: Padding(
padding: const EdgeInsets.all(15.0),
child: Column(
children: <Widget>[
FormField(
mediator: mediator,
labelText: "Username",
validator: _validateNotEmpty,
),
FormField(
mediator: mediator,
labelText: "Email",
keyboardType: TextInputType.emailAddress,
validator: _validateNotEmpty,
),
FormField(
mediator: mediator,
labelText: "Password",
keyboardType: TextInputType.visiblePassword,
validator: (value) {
if (value?.isEmpty == true) {
return 'Password is required';
} else if ((value?.length ?? 0) < 6) {
return 'Password should be at least 6 characters';
}
return null;
},
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: _isFormValid ? _submitForm : null,
child: const Text('Register'),
),
],
),
),
),
);
}
void _submitForm() {
print("Form submitted!");
}
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return RegistrationForm();
}
}
void main() => runApp(MyApp());
RegisterFormMediator是中介者,负责验证整个表单。- 每个
FormField是一个同事,它知道如何验证自己并通知中介者进行整体验证。 - 当所有的字段都通过验证时,提交按钮会被激活。
将表单验证的逻辑与每个字段的具体验证逻辑分离,使得代码更加清晰、易于维护。
总结
中介者模式是一种行为设计模式,它的核心思想是通过引入一个单独的中介对象,来封装一系列对象之间的交互和通信。这样,对象之间不再直接相互通信,而是通过中介者对象来协调。这有助于减少系统中各对象之间的依赖关系,使得系统更加模块化,也更易于维护和扩展。
特点
- 解耦:中介者模式的主要目的是减少多个类之间的耦合,这样单个类的修改不会影响其他类。
- 集中化:所有的交互逻辑都被集中和封装在中介者对象中。
- 灵活性:增加新的同事类或者修改现有的交互逻辑,只需要更改中介者对象。
应用
-
聊天室:一个聊天室应用中,每个用户可以发送消息,但不需要知道其他用户的具体存在。聊天室(中介者)负责接收每个用户的消息并广播给所有其他用户。这样,用户之间的交互被简化,每个用户只需要与聊天室交互。
-
表单验证:一个具有多个输入字段的注册表单。每当用户修改一个字段,都需要进行实时验证。通过使用中介者,每个字段通知中介者其状态是否有效。中介者再根据所有字段的状态决定是否激活提交按钮。
优势:
- 降低耦合:中介者模式确保对象不直接相互通信,而是通过中介者进行交互,这降低了系统中对象之间的依赖。
- 集中控制交互:由于交互逻辑集中在中介者对象中,更改或扩展交互逻辑变得更加简单。
挑战:
- 中介者的复杂性:随着系统规模的增长,中介者对象可能会变得非常复杂,这可能会导致维护困难。
- 性能问题:过度使用中介者可能会导致性能问题,因为所有的交互都需要通过中介者进行。
结论
中介者模式为处理对象之间的交互提供了一种非常有效的方法,尤其是当交互变得复杂时。但它也引入了新的挑战,特别是在中介者对象变得非常庞大和复杂时。在实际应用中,应该根据实际需求和场景权衡是否使用中介者模式。
希望对您有所帮助谢谢!!!****