Repository Pattern : qu'est-ce que c'est, le patron d'abstraction de données dans iOS et Android

Auteur : IT Sectr Publié le : 2026-02-17 Temps de lecture : 7 min

Repository Pattern — un patron qui ajoute une couche d'abstraction entre la logique métier et les sources de données. Au lieu d'appeler directement l'API, la base de données ou le cache, le Repository fournit une interface unifiée pour obtenir et stocker les données. Cela simplifie les tests et le changement entre les sources. En savoir plus dans la documentation Android Data Layer.

Points clés

  • Repository Pattern — une couche entre la logique métier et les sources de données (API, BD, cache)
  • DataSource — classes séparées pour chaque source : RemoteDataSource, LocalDataSource
  • Source unique de vérité — le Repository devient la seule source de données pour la couche UI
  • Tests — le Repository est facilement remplacé par un objet mock via DI pour les tests unitaires
  • Compatibilité — fonctionne avec MVVM, Clean Architecture et d'autres patrons architecturaux

Qu'est-ce que le Repository Pattern dans le développement mobile ?

Repository Pattern est un patron structurel qui isole la logique métier de l'accès direct aux sources de données. Au lieu qu'une Activity, UIViewController ou ViewModel appelle directement Retrofit, URLSession, Room ou CoreData, elles communiquent avec le Repository. Le Repository décide d'où obtenir les données — du réseau, de la base de données ou du cache — et retourne le résultat dans un format unifié. Cela implémente le principe de responsabilité unique — l'UI ne sait pas comment ni d'où les données ont été obtenues.

Les composants du Repository incluent une interface (protocole), une implémentation et un ou plusieurs DataSources. Un DataSource est une classe qui travaille avec une seule source : RemoteDataSource appelle l'API via un client HTTP, LocalDataSource lit et écrit dans la base de données. Le Repository reçoit les DataSources via le constructeur (Injection de Dépendances) et décide quelle source utiliser. Par exemple, lors de la demande d'une liste d'utilisateurs, le Repository vérifie d'abord le cache, puis la base de données, puis le réseau.

Avantages du Repository Pattern : l'isolation des changements de sources de données (changements d'API, migrations de BD) n'affecte pas la couche UI ; les tests unitaires via le remplacement du Repository ou DataSource ; la mise en cache est transparente pour l'UI ; le passage entre les modes en ligne et hors ligne sans modifier la logique d'écran. La communauté Android recommande le Repository comme couche obligatoire dans Clean Architecture.

Repository Pattern dans iOS avec Swift : implémentation et exemple

Implémentation iOS du Repository est construite sur les protocoles Swift. Le protocole Repository déclare des méthodes pour obtenir et stocker les données. L'implémentation réelle est injectée via l'initialiseur — cela permet de remplacer l'implémentation dans les tests et les aperçus SwiftUI. Les DataSources sont également déclarés comme protocoles : Protocol RemoteDataSource, Protocol LocalDataSource. La ViewModel ou l'Interactor ne connaît pas d'implémentation spécifique — seulement le protocole Repository.

swift
protocol UserRepository {
    func getUsers() async throws -> [User]
}

protocol UserRemoteDataSource {
    func fetchUsers() async throws -> [User]
}

protocol UserLocalDataSource {
    func getCachedUsers() throws -> [User]
    func saveUsers(_: [User]) throws
}

final class UserRepositoryImpl: UserRepository {
    private let remote: UserRemoteDataSource
    private let local: UserLocalDataSource

    init(remote: UserRemoteDataSource, local: UserLocalDataSource) {
        self.remote = remote
        self.local = local
    }

    func getUsers() async throws -> [User] {
        if let cached = try? local.getCachedUsers() {
            return cached
        }
        let users = try await remote.fetchUsers()
        try local.saveUsers(users)
        return users
    }
}

Injection de Dépendances dans iOS pour Repository est généralement configurée via une fabrique ou un conteneur DI (Swinject, Factory). Dans les tests, le protocole UserRepository est remplacé par une implémentation mock qui retourne des données prédéfinies. Async-await rend le code synchrone et lisible sans closures ni délégués. Pour la réactivité avec Combine, les méthodes du Repository retournent AnyPublisher au lieu de async throws.

Repository Pattern dans Android avec Kotlin : exemple avec Flow

Implémentation Android du Repository utilise largement Kotlin Coroutines et Flow pour les opérations asynchrones. Google recommande le Repository dans le guide officiel d'architecture Android (Android Architecture Components). Le Repository accepte RemoteDataSource (Retrofit) et LocalDataSource (Room) via le constructeur, et la ViewModel s'abonne à un Flow du Repository. Le Repository gère la stratégie de données : cache d'abord, réseau d'abord, ou toujours le réseau avec écriture dans le cache.

kotlin
interface UserRepository {
    fun getUsers(): Flow<Result<List<User>>>
}

interface UserRemoteDataSource {
    suspend fun fetchUsers(): List<User>
}

interface UserLocalDataSource {
    fun getCachedUsers(): Flow<List<User>>
    suspend fun saveUsers(users: List<User>)
}

class UserRepositoryImpl(
    private val remote: UserRemoteDataSource,
    private val local: UserLocalDataSource
) : UserRepository {

    override fun getUsers(): Flow<Result<List<User>>> = flow {
        emit(Result.Loading)
        local.getCachedUsers().collect { cached ->
            if (cached.isNotEmpty()) {
                emit(Result.Success(cached))
            }
        }
        try {
            val users = remote.fetchUsers()
            local.saveUsers(users)
            emit(Result.Success(users))
        } catch (e: Exception) {
            emit(Result.Error(e))
        }
    }
}

Wrapper Result dans l'exemple ci-dessus est standard pour Android : une classe scellée Result informe la ViewModel de l'état de chargement (Loading, Success, Error). La ViewModel s'abonne via collect et met à jour StateFlow ou LiveData. Repository avec Flow notifie automatiquement l'UI des changements dans la base de données — c'est une différence clé par rapport aux requêtes uniques où l'UI ne connaît pas les changements sans mise à jour manuelle.

DataSource : Remote, Local et mise en cache des données

DataSource — classes responsables du travail avec une source de données spécifique. RemoteDataSource utilise un client HTTP (URLSession, Retrofit, Ktor) pour obtenir des données de l'API. LocalDataSource travaille avec le stockage local (CoreData, Realm, Room, UserDefaults, DataStore). Chaque DataSource a une responsabilité étroite : RemoteDataSource connaît uniquement le format de la requête API, LocalDataSource — le schéma de la base de données. Le Repository les combine, implémentant une stratégie de mise en cache.

DataSourcePlateforme iOSPlateforme AndroidSource
RemoteURLSession + CodableRetrofit + Moshi/GsonAPI REST / GraphQL
Local (BD)CoreData, SwiftDataRoom, SQLDelightSQLite sur l'appareil
Local (cache)NSCache, UserDefaultsDataStore, EncryptedSPEn mémoire / disque
PréférencesUserDefaults, KeychainSharedPreferences, EncryptedSPParamètres, jetons

Stratégies de mise en cache dans Repository : Cache-First (cache d'abord, puis chargement en arrière-plan), Network-Only (réseau uniquement, pour les écrans de paiement), Network-First-With-Cache-Backup (réseau d'abord, fallback vers le cache en cas d'erreur). Le choix de la stratégie dépend du scénario : une liste de pays peut être mise en cache longtemps, les taux de change — pendant 15 minutes, le solde du portefeuille — uniquement depuis le réseau. Le Repository implémente la stratégie et la modifie sans changer la ViewModel ou l'UI.

Repository Pattern vs Service Layer : différences et choix

Repository et Service sont des patrons différents avec des fonctions qui se chevauchent. Repository est responsable de l'accès aux données et de leur mise en cache, retournant des modèles de données. Service (ou Interactor, Use Case) contient la logique métier : validation, transformation des données, orchestration d'appels à plusieurs Repositories. Service peut combiner UserRepository, OrderRepository et NotificationRepository pour traiter une commande. Repository ne contient pas de logique métier — seulement CRUD et mise en cache.

Quand choisir Repository — navigation de données avec plusieurs sources (API + BD + cache), architecture offline-first, besoin de mise en cache et de changement transparent de sources. Repository est obligatoire dans Clean Architecture et recommandé par Google pour les applications Android. Dans l'architecture VIPER sur iOS, le rôle de Repository est joué par la couche Interactor, qui interagit avec Manager ou Service pour l'accès aux données.

Quand Service suffit — applications simples avec une seule source de données, écrans en lecture seule sans écriture, projets sans mode hors ligne. Dans ces cas, DataSource est utilisé directement par la ViewModel ou le Presenter, et Repository devient une couche superflue. Cependant, ajouter Repository tôt ne nécessite pas d'effort important et simplifie l'ajout futur de mise en cache et de tests.

Foire aux questions

En quoi Repository diffère-t-il de DataSource ?

DataSource est une classe qui travaille avec une seule source (API, BD, cache). Repository est une classe qui gère plusieurs DataSources et fournit une interface unifiée. Le Repository décide quel DataSource utiliser et coordonne la mise en cache. DataSource ne connaît pas l'existence d'autres sources ; Repository ne connaît pas les détails d'implémentation de chaque source.

Repository est-il nécessaire dans iOS avec SwiftUI ?

Oui, Repository est utile dans SwiftUI pour séparer les données de la View. La ViewModel s'abonne à un Publisher du Repository, et le Repository gère la mise en cache et la synchronisation. Dans les applications simples, URLSession peut être utilisé directement dans la ViewModel, mais pour la testabilité et l'évolutivité, Repository est préférable. Apple n'impose pas le patron, mais il est compatible avec SwiftData et Network.framework.

Comment tester Repository avec plusieurs DataSources ?

Les DataSources sont remplacés par des objets mock via l'Injection de Dépendances. Le test crée un RemoteDataSource mock (retourne du JSON prédéfini) et un LocalDataSource mock (vérifie que les données sont sauvegardées). Le Repository est testé isolément : la stratégie de cache, la gestion des erreurs et l'ordre correct des appels sont vérifiés. Pour les tests d'intégration, on utilise TestDispatcher (Kotlin) ou MainActor.run (Swift).

Peut-on utiliser Repository sans interface (protocole) ?

C'est possible mais déconseillé. Sans protocole, il est impossible de remplacer l'implémentation dans les tests et les aperçus. En Kotlin, l'interface Repository permet de remplacer l'implémentation via DI (Dagger, Hilt, Koin). En Swift, le protocole Repository est obligatoire pour tester le code async-await et Combine. L'exception concerne les projets simples avec une seule source de données où Repository n'a pas de logique de cache.

Qu'est-ce que l'offline-first dans le contexte de Repository ?

Offline-first est une stratégie où l'application fonctionne sans Internet en utilisant des données locales. Repository joue un rôle clé : il retourne d'abord les données du DataSource local, puis se synchronise avec le serveur en arrière-plan. L'utilisateur voit les données instantanément, et Repository les met à jour après le chargement depuis le réseau. Room avec Flow fournit des mises à jour réactives de l'UI lorsque les données changent dans la base de données locale.

Résumé

  • Repository Pattern — une couche d'abstraction entre l'UI et les sources de données
  • DataSource — classes séparées pour l'API, la BD et le cache
  • Protocoles — nécessaires pour les tests et le remplacement d'implémentations
  • Stratégies de cache — Cache-First, Network-Only, Network-First-With-Cache-Backup
  • iOS — async-await ou Combine avec des protocoles
  • Android — Kotlin Flow + Room + Retrofit, approche recommandée par Google
  • Tests — DataSources mock via DI, vérification des stratégies de cache

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi