Menu
Coddy logo textTech

Patron Dépôt

Fait partie de la section Programmation Orientée Objet du Journey Dart de Coddy. Leçon 100 sur 110.

Le pattern Repository sépare la logique d’accès aux données de la logique métier en créant une couche d’abstraction entre votre application et les sources de données. Au lieu de faire interagir directement vos classes avec des bases de données, des API ou des fichiers, elles travaillent avec un repository qui gère toutes les opérations sur les données.

Le modèle définit une interface pour les opérations sur les données, et les implémentations concrètes gèrent le mécanisme de stockage réel. Cela facilite le remplacement des sources de données sans modifier votre logique métier :

// Entité
class User {
  final int id;
  final String name;
  User(this.id, this.name);
}

// Interface du dépôt
abstract class UserRepository {
  User? getById(int id);
  List<User> getAll();
  void save(User user);
  void delete(int id);
}

// Implémentation en mémoire
class InMemoryUserRepository implements UserRepository {
  final Map<int, User> _users = {};

  @override
  User? getById(int id) => _users[id];

  @override
  List<User> getAll() => _users.values.toList();

  @override
  void save(User user) => _users[user.id] = user;

  @override
  void delete(int id) => _users.remove(id);
}

void main() {
  UserRepository repo = InMemoryUserRepository();
  
  repo.save(User(1, 'Alice'));
  repo.save(User(2, 'Bob'));
  
  print(repo.getById(1)?.name);  // Alice
  print(repo.getAll().length);    // 2
}

Votre logique métier dépend uniquement de l’interface UserRepository. Vous pourriez plus tard créer un DatabaseUserRepository ou un ApiUserRepository qui implémente la même interface, et remplacer les implémentations sans modifier le code qui utilise le référentiel. Ce modèle est essentiel pour les applications testables et faciles à maintenir, dont les sources de données peuvent évoluer au fil du temps.

challenge icon

Défi

Facile

Construisons un système d’inventaire de produits en utilisant le pattern Repository ! Tu vas créer une couche d’abstraction qui sépare la manière dont les produits sont stockés de la manière dont ils sont utilisés, ce qui facilitera le remplacement des implémentations de stockage sans modifier la logique métier.

Tu organiseras ton code en deux fichiers :

  • product_repository.dart : ce fichier contient tes classes d’entité et de repository. Commence par une classe Product qui possède des champs final pour id (int), name (String) et price (double). Définis ensuite une classe abstraite ProductRepository qui déclare le contrat des opérations sur les données : getById(int id) renvoyant un Product nullable, getAll() renvoyant une liste de produits, save(Product product) pour stocker un produit et delete(int id) pour en supprimer un. Enfin, crée une classe InMemoryProductRepository qui implémente cette interface en utilisant une Map<int, Product> pour le stockage.
  • main.dart : importe ton fichier de repository et montre le pattern Repository en action. Crée une instance de InMemoryProductRepository, mais stocke-la dans une variable de type ProductRepository — cela montre que ton code dépend de l’interface, et non de l’implémentation. Enregistre trois produits : Laptop (id : 1, price : 999.99), Mouse (id : 2, price : 29.99) et Keyboard (id : 3, price : 79.99). Récupère et affiche ensuite le produit dont l’id est 2 au format Found: [name] - $[price]. Supprime le produit dont l’id est 1. Enfin, affiche le nombre de produits restants sous la forme Products in stock: [count].

L’intérêt de ce pattern est que ton code principal ne connaît que l’interface ProductRepository. Tu pourrais plus tard créer un DatabaseProductRepository ou un ApiProductRepository et le remplacer sans modifier la moindre partie de la logique métier !

Sortie attendue :

Found: Mouse - $29.99
Products in stock: 2

Essayez vous-même

import 'product_repository.dart';

void main() {
  // Créer le dépôt - notez que le type est l'interface, pas l'implémentation
  // TODO: Créer un InMemoryProductRepository et le stocker dans une variable ProductRepository
  
  // TODO: Enregistrer trois produits :
  // - Laptop (id: 1, price: 999.99)
  // - Mouse (id: 2, price: 29.99)
  // - Keyboard (id: 3, price: 79.99)
  
  // TODO: Récupérer le produit avec l'id 2 et afficher : "Found: [name] - $[price]"
  
  // TODO: Supprimer le produit avec l'id 1
  
  // TODO: Afficher le nombre de produits restants : "Products in stock: [count]"
}
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation Orientée Objet

Entraînez-vous par vous-même : Compilateur Dart en ligne