Pola Repository
Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan Dart di Coddy. Pelajaran 100 dari 110.
Pola Repository memisahkan logika akses data dari logika bisnis dengan membuat lapisan abstraksi antara aplikasi dan sumber data. Alih-alih membuat class-mu berinteraksi langsung dengan database, API, atau file, class tersebut bekerja dengan repository yang menangani semua operasi data.
Pola ini menentukan antarmuka untuk operasi data, sedangkan implementasi konkret menangani mekanisme penyimpanan yang sebenarnya. Dengan begitu, kamu bisa mengganti sumber data dengan mudah tanpa mengubah logika bisnis:
// Entitas
class User {
final int id;
final String name;
User(this.id, this.name);
}
// Antarmuka repository
abstract class UserRepository {
User? getById(int id);
List<User> getAll();
void save(User user);
void delete(int id);
}
// Implementasi dalam memori
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
}Logika bisnis kamu hanya bergantung pada antarmuka UserRepository. Nantinya, kamu dapat membuat DatabaseUserRepository atau ApiUserRepository yang mengimplementasikan antarmuka yang sama, lalu mengganti implementasinya tanpa mengubah kode apa pun yang menggunakan repositori tersebut. Pola ini penting untuk aplikasi yang dapat diuji dan mudah dipelihara, terutama saat sumber data dapat berubah seiring waktu.
Tantangan
MudahMari kita bangun sistem inventaris produk menggunakan pola Repository! Kamu akan membuat lapisan abstraksi yang memisahkan cara produk disimpan dari cara produk digunakan, sehingga kamu dapat mengganti implementasi penyimpanan dengan mudah tanpa mengubah logika bisnis.
Kamu akan mengatur kodemu ke dalam dua file:
product_repository.dart: File ini berisi entity dan class repository-mu. Mulailah dengan classProductyang memiliki fieldfinaluntukid(int),name(String), danprice(double). Lalu, definisikan class abstrakProductRepositoryyang menyatakan kontrak untuk operasi data:getById(int id)yang mengembalikanProductyang bisa bernilai null,getAll()yang mengembalikan list produk,save(Product product)untuk menyimpan produk, dandelete(int id)untuk menghapus produk. Terakhir, buatInMemoryProductRepositoryyang mengimplementasikan antarmuka ini menggunakanMap<int, Product>sebagai penyimpanan.main.dart: Impor file repository-mu dan tunjukkan pola Repository. BuatInMemoryProductRepository, tetapi simpan dalam variabel bertipeProductRepository. Ini menunjukkan bahwa kodemu bergantung pada antarmuka, bukan implementasinya. Simpan tiga produk:Laptop(id: 1, price: 999.99),Mouse(id: 2, price: 29.99), danKeyboard(id: 3, price: 79.99). Lalu, ambil dan cetak produk dengan id 2 dalam formatFound: [name] - $[price]. Hapus produk dengan id 1. Terakhir, cetak jumlah produk yang tersisa sebagaiProducts in stock: [count].
Keunggulan pola ini adalah kode utamamu hanya mengenal antarmuka ProductRepository. Nantinya, kamu dapat membuat DatabaseProductRepository atau ApiProductRepository dan menggantinya tanpa mengubah logika bisnis apa pun!
Output yang diharapkan:
Found: Mouse - $29.99
Products in stock: 2Coba sendiri
import 'product_repository.dart';
void main() {
// Buat repository. Perhatikan bahwa tipenya adalah interface, bukan implementasinya
// TODO: Buat InMemoryProductRepository dan simpan dalam variabel ProductRepository
// TODO: Simpan tiga produk:
// - Laptop (id: 1, price: 999.99)
// - Mouse (id: 2, price: 29.99)
// - Keyboard (id: 3, price: 79.99)
// TODO: Ambil produk dengan id 2 dan cetak: "Found: [name] - $[price]"
// TODO: Hapus produk dengan id 1
// TODO: Cetak jumlah produk yang tersisa: "Products in stock: [count]"
}
Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.
Semua pelajaran di Pemrograman Berorientasi Objek
1Dasar-Dasar OOP
file Eksternallibrary dan ImporPengantar OOPClass dan ObjectKata kunci thismethodVariabel InstanceDasar-Dasar ConstructorRingkasan: Kalkulator Sederhana4Keamanan Null
Pengantar Keamanan NullBisa Null vs Tidak Bisa NullOperator ? dan !Kata Kunci late dan Keamanan NullOperator Penanganan NullKeamanan Null dalam classRangkuman: Sistem Profil Pengguna7class Abstrak & Antarmuka
class AbstrakMethod abstrakAntarmuka di DartAntarmuka ImplisitMengimplementasikan vs MemperluasBeberapa AntarmukaRingkasan: Kalkulator Bentuk10Koleksi dan Generik
Gambaran Umum list, set, dan MapKoleksi dengan Tipe AmanKelas GenerikMetode GenerikBatasan GenerikIterable dan IteratorUlasan: Penyimpanan Generik2Konstruktor dalam Dart
Konstruktor DefaultKonstruktor BernamaInitializer ListsKonstruktor KonstanKonstruktor FactoryKonstruktor RedirectingRangkuman, Pembuat Bentuk5Enkapsulasi
Member Publik vs PrivatKonvensi Prefiks _Privasi Tingkat libraryPendalaman Getter & SetterPenyembunyian InformasiRingkasan: Catatan Siswa8Mixin
Pengantar MixinMembuat MixinMenggunakan Beberapa MixinKata Kunci on pada MixinMixin vs. PewarisanMixin vs. InterfaceRangkuman: Sistem Hewan3Property Class
Anggota Instance vs StaticField Final dan ConstVariabel LateMethod dan Field StaticGetter dan SetterRangkuman: Pengelola Rekening Bank6Pewarisan
Pewarisan DasarKata Kunci superPenimpaan methodAnotasi @overrideKata Kunci class finalKonstruktor dan PewarisanRangkuman, Hierarki Karyawan9Polimorfisme
Dasar-Dasar PolimorfismePolimorfisme melalui AntarmukaPemeriksaan Tipe saat RuntimeOperator is & asKata Kunci KovarianRangkuman: Pemroses Pembayaran12OOP Asinkron
Futures & async/awaitDasar-Dasar StreamPengontrol StreamKonstruktor AsinkronAsync dalam Method ClassRangkuman: Pengambil Data15Pola Desain Bagian 2
Pola CommandPola AdapterPola DecoratorPola Template MethodPola StatePola CompositePola RepositoryLatihan sendiri: Compiler Dart online