https://github.com/uproid/instancer
A simple, lightweight factory registry for Dart that makes creating instances of registered types easy and flexible.
https://github.com/uproid/instancer
dart finch flutter instance pub
Last synced: 2 months ago
JSON representation
A simple, lightweight factory registry for Dart that makes creating instances of registered types easy and flexible.
- Host: GitHub
- URL: https://github.com/uproid/instancer
- Owner: uproid
- License: mit
- Created: 2025-12-05T21:52:19.000Z (4 months ago)
- Default Branch: main
- Last Pushed: 2025-12-05T22:23:56.000Z (4 months ago)
- Last Synced: 2026-01-13T20:44:15.311Z (2 months ago)
- Topics: dart, finch, flutter, instance, pub
- Language: Dart
- Homepage: https://pub.dev/packages/instancer
- Size: 20.5 KB
- Stars: 4
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- Funding: .github/FUNDING.yml
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
- Security: SECURITY.md
Awesome Lists containing this project
README
# Instancer
[](https://pub.dev/packages/instancer)
[](https://buymeacoffee.com/uproid)
[](https://github.com/uproid/instancer/issues?q=is%3Aissue+is%3Aclosed)
[](https://github.com/uproid/instancer/issues)
[](https://github.com/uproid/instancer/blob/main/CONTRIBUTING.md)
A simple, lightweight factory registry for Dart that makes creating instances of registered types easy and flexible.
Perfect for dependency injection, prototyping, configuration management, and testing!
## Features
โจ **Simple API**: Just 5 intuitive methods to learn
๐ฏ **Type-safe**: Full generic type support
๐ชถ **Lightweight**: Zero dependencies
๐ง **Flexible**: Register any factory function
๐งช **Testable**: Easy to clear and reset for testing
## Getting started
Add this to your `pubspec.yaml`:
```yaml
dependencies:
instancer: ^1.0.0
```
Then import it:
```dart
import 'package:instancer/instancer.dart';
```
## Usage
### ๐ Quick Start
```dart
import 'package:instancer/instancer.dart';
class User {
final String name;
final int age;
User({required this.name, required this.age});
}
void main() {
// 1๏ธโฃ Register a factory function
Instancer.register(() => User(name: 'Guest', age: 18));
// 2๏ธโฃ Create instances anywhere in your code
final user1 = Instancer.create();
final user2 = Instancer.create();
print(user1.name); // Output: Guest
print(identical(user1, user2)); // Output: false (different instances)
}
```
### ๐ฆ Real-World Examples
#### Example 1: Configuration Management
```dart
class AppConfig {
final String apiUrl;
final bool debugMode;
final int timeout;
AppConfig({
required this.apiUrl,
required this.debugMode,
required this.timeout,
});
}
void main() {
// Development environment
Instancer.register(
() => AppConfig(
apiUrl: 'http://localhost:3000',
debugMode: true,
timeout: 30,
),
);
// Use it anywhere in your app
final config = Instancer.create();
print(config.apiUrl); // http://localhost:3000
// Switch to production (just re-register)
Instancer.register(
() => AppConfig(
apiUrl: 'https://api.production.com',
debugMode: false,
timeout: 10,
),
);
final prodConfig = Instancer.create();
print(prodConfig.apiUrl); // https://api.production.com
}
```
#### Example 2: Dependency Injection
```dart
class Database {
void query(String sql) => print('Executing: $sql');
}
class UserRepository {
final Database database;
UserRepository({required this.database});
void save(String name) {
database.query("INSERT INTO users (name) VALUES ('$name')");
}
}
class UserService {
final UserRepository repository;
UserService({required this.repository});
void createUser(String name) {
print('Creating user: $name');
repository.save(name);
}
}
void main() {
// Register dependencies in order
Instancer.register(() => Database());
Instancer.register(
() => UserRepository(database: Instancer.create()),
);
Instancer.register(
() => UserService(repository: Instancer.create()),
);
// Use the service
final userService = Instancer.create();
userService.createUser('Alice');
// Output:
// Creating user: Alice
// Executing: INSERT INTO users (name) VALUES ('Alice')
}
```
#### Example 3: Testing with Mocks
```dart
abstract class ApiClient {
Future fetchData();
}
class RealApiClient implements ApiClient {
@override
Future fetchData() async {
// Real network call
return 'Real data from server';
}
}
class MockApiClient implements ApiClient {
@override
Future fetchData() async {
// Mock data for testing
return 'Mock data';
}
}
void main() {
// Production code
Instancer.register(() => RealApiClient());
// In your tests, just re-register with mock
Instancer.register(() => MockApiClient());
final client = Instancer.create();
client.fetchData().then(print); // Output: Mock data
// Clean up after tests
Instancer.clear();
}
```
#### Example 4: Prototype Pattern
```dart
class EmailTemplate {
final String subject;
final String body;
final List recipients;
EmailTemplate({
required this.subject,
required this.body,
this.recipients = const [],
});
@override
String toString() => 'Email: $subject to ${recipients.length} recipients';
}
void main() {
// Register a prototype template
Instancer.register(
() => EmailTemplate(
subject: 'Welcome!',
body: 'Welcome to our service',
recipients: ['user@example.com'],
),
);
// Create multiple emails from the same template
final email1 = Instancer.create();
final email2 = Instancer.create();
print(email1); // Email: Welcome! to 1 recipients
print(email2); // Email: Welcome! to 1 recipients
print('Same instance? ${identical(email1, email2)}'); // false
}
```
#### Example 5: Factory with State
```dart
class Logger {
static int _instanceCount = 0;
final int id;
Logger() : id = ++_instanceCount;
void log(String message) {
print('[Logger $id] $message');
}
}
void main() {
// Each creation increases the counter
Instancer.register(() => Logger());
final logger1 = Instancer.create();
final logger2 = Instancer.create();
final logger3 = Instancer.create();
logger1.log('First message'); // [Logger 1] First message
logger2.log('Second message'); // [Logger 2] Second message
logger3.log('Third message'); // [Logger 3] Third message
}
```
## API Reference
### `register(T Function() factory)`
Registers a factory function for type `T`.
```dart
Instancer.register(() => User(name: 'John', age: 25));
```
**Parameters:**
- `factory`: A function that returns a new instance of type `T`
### `create()`
Creates a new instance of type `T` using the registered factory.
```dart
final user = Instancer.create();
```
**Returns:** A new instance of type `T`
**Throws:** `StateError` if no factory is registered for type `T`
### `isRegistered()`
Checks if a factory is registered for type `T`.
```dart
if (Instancer.isRegistered()) {
print('User factory is registered!');
}
```
**Returns:** `true` if registered, `false` otherwise
### `unregister()`
Removes the factory for type `T`.
```dart
final removed = Instancer.unregister();
print('Factory removed: $removed');
```
**Returns:** `true` if a factory was removed, `false` if none existed
### `clear()`
Removes all registered factories. Useful for testing or resetting state.
```dart
Instancer.clear();
```
### `count`
Returns the number of registered factories.
```dart
print('Total registered factories: ${Instancer.count}');
```
## Why Instancer?
| Feature | Instancer | Traditional Singleton | Factory Pattern |
|---------|-----------|----------------------|-----------------|
| No inheritance required | โ
| โ | โ
|
| No code generation | โ
| โ
| โ
|
| Multiple instances | โ
| โ | โ
|
| Easy to test | โ
| โ | โ
|
| Dynamic registration | โ
| โ | โ |
| Zero dependencies | โ
| โ
| โ
|
### Benefits:
- **No inheritance required**: Your classes don't need to extend anything
- **No code generation**: Works without `build_runner` or code generation
- **Pure Dart**: No platform-specific code, works everywhere (Flutter, CLI, Web)
- **Flexible**: Register simple constructors or complex initialization logic
- **Testable**: Easy to swap implementations for mocking in tests
- **Simple**: Only 5 methods to learn - `register`, `create`, `isRegistered`, `unregister`, `clear`
## Common Use Cases
โ
**Dependency Injection** - Register and inject dependencies
โ
**Configuration Management** - Switch between dev/prod configs
โ
**Testing** - Replace real implementations with mocks
โ
**Prototype Pattern** - Create multiple instances from templates
โ
**Factory Pattern** - Centralized instance creation
โ
**Plugin Systems** - Register and create plugin instances
## Tips & Best Practices
### 1. Register early, use anywhere
```dart
// In your app initialization
void setupDependencies() {
Instancer.register(() => SqliteDatabase());
Instancer.register(() => HttpApiClient());
Instancer.register(() => AuthService());
}
// Use anywhere in your app
final auth = Instancer.create();
```
### 2. Use for environment-specific configurations
```dart
void setupConfig(Environment env) {
if (env == Environment.dev) {
Instancer.register(() => DevConfig());
} else {
Instancer.register(() => ProdConfig());
}
}
```
### 3. Clean up in tests
```dart
void main() {
setUp(() {
Instancer.register(() => MockService());
});
tearDown(() {
Instancer.clear(); // Always clean up!
});
test('service works', () {
final service = Instancer.create();
// Test...
});
}
```
## Contributing
Contributions are welcome! Please read our [CONTRIBUTING.md](CONTRIBUTING.md) for details.
1. Check existing [issues](https://github.com/uproid/instancer/issues)
2. Create a new issue or submit a pull request
3. Follow the existing code style
## License
MIT License - see the [LICENSE](LICENSE) file for details.
## Author
Created with โค๏ธ by [Uproid](https://github.com/uproid)
---
**Like this package?** Give it a โญ on [GitHub](https://github.com/uproid/instancer)!