Menu
CoddyTech

Patron Dépôt

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

Le patron de dépôt 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 que vos classes interagissent directement avec des bases de données, des API ou des fichiers, elles utilisent un dépôt 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 permet de remplacer facilement les 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 créer plus tard un DatabaseUserRepository ou un ApiUserRepository qui implémente la même interface, et remplacer les implémentations sans modifier le code qui utilise le dépôt. Ce modèle est essentiel pour créer des applications faciles à tester et à 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 motif 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 dans deux fichiers :

  • product_repository.dart : ce fichier contient tes classes d’entité et de dépôt. 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), qui renvoie un Product nullable, getAll(), qui renvoie 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 dépôt et montre le motif Repository en action. Crée un InMemoryProductRepository, mais stocke-le 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, prix : 999.99), Mouse (id : 2, prix : 29.99) et Keyboard (id : 3, prix : 79.99). Récupère ensuite le produit dont l’id est 2 et affiche-le 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’avantage de ce motif, c’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 logique métier !

Résultat attendu :

Found: Mouse - $29.99
Products in stock: 2

Essayez vous-même

import 'product_repository.dart';

void main() {
  // Créer un dépôt - noter que le type est l’interface, et non 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 id 2 et afficher : "Found: [name] - $[price]"
  
  // TODO: Supprimer le produit avec 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