Create a flexible plugin architecture using abstract classes, mixins, and extensions. Build a system where plugins can be dynamically registered and executed with shared utilities.
Requirements
Create an abstract Plugin class with init, execute, and cleanup methods
Use mixins for shared functionality (Logging, Timing, Validation)
Build a PluginManager that registers and runs plugins
Create example plugins: TextProcessor, DataExporter, ImageResizer
Track plugin execution time and status
import 'dart:math';
// Step 1: Mixins for shared functionality
mixin Logger {
void log(String message) {
print('[${DateTime.now().toIso8601String()}] ${runtimeType}: $message');
}
void warn(String message) {
print('ā ļø [${runtimeType}] $message');
}
void error(String message) {
print('ā [${runtimeType}] $message');
}
}
mixin Timer {
final Stopwatch _stopwatch = Stopwatch();
Duration get elapsed => _stopwatch.elapsed;
bool get isRunning => _stopwatch.isRunning;
void startTimer() => _stopwatch.start();
void stopTimer() => _stopwatch.stop();
void resetTimer() => _stopwatch.reset();
String get elapsedFormatted {
final ms = _stopwatch.elapsedMilliseconds;
if (ms < 1000) return '${ms}ms';
return '${(ms / 1000).toStringAsFixed(2)}s';
}
}
mixin Validator {
bool validateInput(Map input, List requiredFields) {
for (var field in requiredFields) {
if (!input.containsKey(field) || input[field] == null) {
return false;
}
}
return true;
}
}
// Step 2: Plugin status enum
enum PluginStatus { uninitialized, ready, running, completed, failed }
// Step 3: Abstract plugin class
abstract class Plugin with Logger, Timer, Validator {
final String name;
final String version;
PluginStatus _status = PluginStatus.uninitialized;
Plugin(this.name, this.version);
PluginStatus get status => _status;
Future init();
Future