Dart & Flutter

[Flutter] Repository Pattern

ju_young 2023. 5. 4. 16:42
728x90

일반적인 repository pattern은 다음과 같이 business layer, repository layer, data source로 구성되어있다.

각각은 간단하게 다음과 같이 설명할 수 있다.

  • business layer: 실제로 controller 또는 service로 사용됨.
  • repository layer: 특정 api에 맞게 data를 주고받을 수 있게하는 abstract한 format이다. 다시 말해 SQLite를 사용한다면 SQLite에 맞게, MongoDB를 사용한다면 MongoDB에 맞게 만들 수 있게 만들어놓는 틀이다. 는 business layer가 직접 data에 접근할 수 없게 만들어주기도 한다.
  • data source: RESTful API, SQLite, MongoDB와 같은 것들을 말한다.

한 블로그에서는 bookstore 서비스를 예시로 설명하였는데 간단하게 각각이 코드로 어떻게 구현되어있는지 확인해보겠다. (data source의 경우 임의로 구현해낸 것이라고한다.)

 

Data Source

class VirtualDB {
  List<Map<String, dynamic>> _items = [];
  static final VirtualDB _db = VirtualDB._privateConstructor();

  VirtualDB._privateConstructor();

  factory VirtualDB() {
    return _db;
  }

  Future<void> insert(Map<String, dynamic> item) async {
    item['id'] = Random().nextInt(1000);
    _items.add(item);
  }

  Future<void> remove(int id) async {
    _items.removeWhere((item) => item['id'] == id);
  }

  Future<void> update(Map<String, dynamic> updatedItem) async {
    int i = _items.indexWhere((item) => item['id'] == updatedItem['id']);
    _items[i] = updatedItem;
  }

  Future<List<Map<String, dynamic>>> list() async {
    await Future.delayed(Duration(milliseconds: 800));
    return _items;
  }

  Future<Map<String, dynamic>?> findOne(int id) async {
    return _items.firstWhere((item) => item['id'] == id);
  }
}

 

Repository Layer

abstract class IBookRepository {
  Future<List<Book>> getAll();
  Future<Book?> getOne(int id);
  Future<void> insert(Book book);
  Future<void> update(Book book);
  Future<void> delete(int id);
}

 

Business Layer

class BookRepository implements IBookRepository {

  final VirtualDB _db;

  BookRepository(this._db);

  @override
  Future<List<Book>> getAll() async {
    var items = await _db.list();
    return items.map((item) => Book.fromMap(item)).toList();
  }

  @override
  Future<Book?> getOne(int id) async {
    var item = await _db.findOne(id);
    return item != null ? Book.fromMap(item) : null;
  }

  @override
  Future<void> insert(Book book) async {
    await _db.insert(book.toMap());
  }

  @override
  Future<void> update(Book book) async {
    await _db.update(book.toMap());
  }

  @override
  Future<void> delete(int id) async {
    await _db.remove(id);
  }
}

 

[reference]

https://bloclibrary.dev/#/architecture?id=data-provider

https://blog.logrocket.com/implementing-repository-pattern-flutter/

728x90