CodeBlanks Logo Icon CodeBlanks

Repository

Learn the repository pattern.

Repository

The Repository pattern abstracts data access. The domain layer defines a Repository interface; the data layer implements it. The domain does not know whether data comes from an API or a database.

Example: abstract class ProductRepository { Product fetch(String id); }. Concrete classes: ApiProductRepository, DbProductRepository, MockProductRepository — all implement the same interface.

Advantage: in tests MockProductRepository is used; domain logic is tested without hitting a real API. When the data source changes, only the concrete class changes.

Multiple data sources

The same interface can be implemented by multiple classes: ApiRepo (remote API), DbRepo (local database), CacheRepo (cache). The application decides which to use via configuration.

Cache strategy: CacheRepo checks the cache first; on a miss it falls back to ApiRepo and writes the result to the cache. This is known as the decorator pattern.

The repository interface stays unchanged while the inner implementation can be swapped freely. This makes the code easier to maintain and extend.

Practice Define ProductRepository and a Mock

Define a Product class with final String id; final String name; Product(this.id, this.name);. Define an abstract class ProductRepository with Product fetch(String id);. Define a class MockProductRepository implements ProductRepository with @override Product fetch(String id) => Product(id, 'Kitap');. In main create final repo = MockProductRepository();; add final product = repo.fetch('1'); and print(product.name);.

Starter code

main.dart
void main() {
  // define a Product class (id, name fields)
  // define an abstract ProductRepository (fetch method)
  // define a MockProductRepository (applies the interface)
  // create a mock repo; call fetch; print name
}

Sample solution

main.dart
class Product {
  final String id;
  final String name;
  Product(this.id, this.name);
}

abstract class ProductRepository {
  Product fetch(String id);
}

class MockProductRepository implements ProductRepository {
  @override
  Product fetch(String id) => Product(id, 'Kitap');
}

void main() {
  final repo = MockProductRepository();
  final product = repo.fetch('1');
  print(product.name);
}

Expected output

Kitap

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 Match the repository parts

Term Meaning
Repository Contract
RepositoryImpl Implementation
fetch(id) Read method
save(entity) Write method

2 What does the Repository pattern abstract?

  • UI drawing
  • Data access Correct answer
  • Running tests
  • File reading

Explanation: the Repository abstracts data access; the source stays hidden.

3 Repository implementation

Question
class ApiUserRepository ____ UserRepository { }
Answer
class ApiUserRepository implements UserRepository { }

Explanation: implements applies an interface.

All lessons in Expert