Menu
Coddy logo textTech

Repository Kalıbı

Coddy'nin Dart Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 100 / 110.

Repository deseni, uygulamanız ile veri kaynakları arasında bir soyutlama katmanı oluşturarak veri erişim mantığını iş mantığından ayırır. Sınıflarınızın veritabanları, API'ler veya dosyalarla doğrudan etkileşime girmesi yerine, tüm veri işlemlerini yöneten bir repository ile çalışırlar.

Desen, veri işlemleri için bir arayüz tanımlar ve somut uygulamalar gerçek depolama mekanizmasını yönetir. Bu, iş mantığınızı değiştirmeden veri kaynaklarını değiştirmeyi kolaylaştırır:

// Varlık (Entity)
class User {
  final int id;
  final String name;
  User(this.id, this.name);
}

// Repository arayüzü
abstract class UserRepository {
  User? getById(int id);
  List<User> getAll();
  void save(User user);
  void delete(int id);
}

// Bellek içi implementasyon
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
}

İş mantığınız yalnızca UserRepository arayüzüne bağlıdır. Daha sonra aynı arayüzü uygulayan bir DatabaseUserRepository veya ApiUserRepository oluşturabilir ve depoyu kullanan hiçbir kodu değiştirmeden uygulamaları birbirleriyle değiştirebilirsiniz. Bu desen, veri kaynaklarının zamanla değişebileceği test edilebilir ve bakımı kolay uygulamalar için temeldir.

challenge icon

Görev

Kolay

Repository desenini kullanarak bir ürün envanter sistemi oluşturalım! Ürünlerin nasıl saklandığını nasıl kullanıldıklarından ayıran bir soyutlama katmanı oluşturacaksınız; bu sayede iş mantığını değiştirmeden depolama uygulamalarını değiştirmek kolaylaşacak.

Kodunuzu iki dosya halinde düzenleyeceksiniz:

  • product_repository.dart: Bu dosya, varlık (entity) ve repository sınıflarınızı içerir. id (int), name (String) ve price (double) için final alanlara sahip bir Product sınıfı ile başlayın. Ardından, veri işlemleri için sözleşmeyi bildiren soyut bir ProductRepository sınıfı tanımlayın: null dönebilen bir Product döndüren getById(int id), ürün listesi döndüren getAll(), bir ürünü kaydetmek için save(Product product) ve bir ürünü silmek için delete(int id). Son olarak, depolama için bir Map<int, Product> kullanarak bu arayüzü (interface) uygulayan bir InMemoryProductRepository oluşturun.
  • main.dart: Repository dosyanızı içe aktarın ve Repository desenini iş başında gösterin. Bir InMemoryProductRepository oluşturun ancak bunu ProductRepository tipinde bir değişkende saklayın - bu, kodunuzun uygulamaya değil, arayüze nasıl bağımlı olduğunu gösterir. Üç ürün kaydedin: Laptop (id: 1, price: 999.99), Mouse (id: 2, price: 29.99) ve Keyboard (id: 3, price: 79.99). Ardından id'si 2 olan ürünü getirin ve Found: [name] - $[price] formatında yazdırın. id'si 1 olan ürünü silin. Son olarak, kalan ürünlerin sayısını Products in stock: [count] olarak yazdırın.

Bu desenin gücü, ana kodunuzun yalnızca ProductRepository arayüzünü bilmesidir. Daha sonra bir DatabaseProductRepository veya ApiProductRepository oluşturabilir ve iş mantığından hiçbirini değiştirmeden bunları birbirinin yerine kullanabilirsiniz!

Beklenen çıktı:

Found: Mouse - $29.99
Products in stock: 2

Kopya kağıdı

Repository deseni, uygulamanız ile veri kaynakları arasında bir soyutlama katmanı oluşturarak veri erişim mantığını iş mantığından ayırır.

Veri işlemleri için bir arayüz tanımlayın:

// Varlık (Entity)
class User {
  final int id;
  final String name;
  User(this.id, this.name);
}

// Repository arayüzü
abstract class UserRepository {
  User? getById(int id);
  List<User> getAll();
  void save(User user);
  void delete(int id);
}

Gerçek depolama mekanizmasını yöneten somut uygulamalar oluşturun:

// Bellek içi (In-memory) uygulama
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);
}

Repository'yi arayüzü üzerinden kullanın:

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
}

İş mantığı yalnızca arayüze bağlıdır; bu da repository'yi kullanan kodu değiştirmeden uygulamaları (örneğin, DatabaseUserRepository, ApiUserRepository) değiştirmenize olanak tanır.

Kendin dene

import 'product_repository.dart';

void main() {
  // Depoyu oluşturun - türün uygulama değil, arayüz (interface) olduğuna dikkat edin
  // TODO: Bir InMemoryProductRepository oluşturun ve bunu bir ProductRepository değişkeninde saklayın
  
  // TODO: Üç ürün kaydedin:
  // - Laptop (id: 1, price: 999.99)
  // - Mouse (id: 2, price: 29.99)
  // - Keyboard (id: 3, price: 79.99)
  
  // TODO: id değeri 2 olan ürünü getirin ve yazdırın: "Found: [name] - $[price]"
  
  // TODO: id değeri 1 olan ürünü silin
  
  // TODO: Kalan ürünlerin sayısını yazdırın: "Products in stock: [count]"
}
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler