You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Dart/Flutter中结合GetIt包实现装饰器模式?

在Flutter中用get_it实现装饰器模式

一、Dart中装饰器模式的实现结构

Dart没有专门的interface关键字,但可以用**抽象类(abstract class)**定义核心契约,作用和C#的interface完全一致:

  • 抽象组件:定义抽象类,声明业务核心方法
  • 具体组件:继承抽象类,实现核心方法的基础逻辑
  • 装饰器类:同样继承抽象类,内部持有抽象组件的实例,在调用核心方法的前后添加额外功能

举个日志服务的实现示例:

// 抽象组件(对应C#的interface)
abstract class Logger {
  void log(String message);
}

// 具体组件:基础控制台日志实现
class ConsoleLogger implements Logger {
  @override
  void log(String message) {
    print('Console: $message');
  }
}

// 装饰器1:给日志添加时间戳
class TimestampLoggerDecorator implements Logger {
  final Logger _logger;

  TimestampLoggerDecorator(this._logger);

  @override
  void log(String message) {
    final timestamp = DateTime.now().toIso8601String();
    _logger.log('[$timestamp] $message');
  }
}

// 装饰器2:给日志添加错误标记
class ErrorLoggerDecorator implements Logger {
  final Logger _logger;

  ErrorLoggerDecorator(this._logger);

  @override
  void log(String message) {
    _logger.log('[ERROR] $message');
  }
}

二、结合get_it实现服务的装饰注册

get_it没有像Scrutor那样的内置装饰注册方法,需要手动构建依赖链:

  1. 先注册原始的基础服务实例
  2. 注册装饰后的服务时,从get_it中获取原始服务,注入到装饰器中

基础注册示例

import 'package:get_it/get_it.dart';

final getIt = GetIt.instance;

void setupLocator() {
  // 1. 注册基础服务
  getIt.registerSingleton<Logger>(ConsoleLogger());

  // 2. 注册带时间戳的装饰版服务(用实例名区分不同版本)
  getIt.registerSingleton<Logger>(
    TimestampLoggerDecorator(getIt<Logger>()),
    instanceName: 'timestampLogger',
  );

  // 叠加多个装饰器:错误标记+时间戳
  getIt.registerSingleton<Logger>(
    ErrorLoggerDecorator(TimestampLoggerDecorator(getIt<Logger>())),
    instanceName: 'errorTimestampLogger',
  );
}

// 使用示例
void main() {
  setupLocator();
  
  // 获取基础日志
  final basicLogger = getIt<Logger>();
  basicLogger.log('Hello'); // 输出: Console: Hello

  // 获取带时间戳的日志
  final timestampLogger = getIt<Logger>(instanceName: 'timestampLogger');
  timestampLogger.log('Hello'); // 输出: Console: [2024-05-20T12:34:56.789] Hello

  // 获取带错误标记+时间戳的日志
  final errorLogger = getIt<Logger>(instanceName: 'errorTimestampLogger');
  errorLogger.log('Something went wrong'); // 输出: Console: [2024-05-20T12:34:56.789] [ERROR] Something went wrong
}

默认返回装饰后服务的方式

如果希望默认获取的Logger就是装饰后的版本,可以覆盖原始注册:

void setupLocator() {
  // 先注册基础服务(用lazySingleton延迟加载更高效)
  getIt.registerLazySingleton<Logger>(() => ConsoleLogger());

  // 覆盖默认的Logger注册,返回装饰后的实例
  getIt.registerSingleton<Logger>(
    TimestampLoggerDecorator(getIt<Logger>()),
    overrideExisting: true,
  );
}

内容的提问来源于stack exchange,提问作者Batesias

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 09:22:08