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-mu bekerja dengan repository yang menangani semua operasi data.
Pola ini mendefinisikan antarmuka untuk operasi data, dan implementasi konkret menangani mekanisme penyimpanan yang sebenarnya. Dengan demikian, kamu dapat mengganti sumber data dengan mudah tanpa mengubah logika bisnis:
// Entitas
class User {
final int id;
final String name;
User(this.id, this.name);
}
// Antarmuka repositori
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. Nanti, kamu bisa membuat DatabaseUserRepository atau ApiUserRepository yang mengimplementasikan antarmuka yang sama, lalu mengganti implementasinya tanpa mengubah kode apa pun yang menggunakan repository tersebut. Pola ini penting untuk aplikasi yang dapat diuji dan dipelihara, yang sumber datanya mungkin berubah seiring waktu.
Tantangan
MudahMari kita buat sistem inventaris produk menggunakan pola Repository! Kamu akan membuat lapisan abstraksi yang memisahkan cara produk disimpan dari cara produk digunakan, sehingga implementasi penyimpanan dapat diganti dengan mudah tanpa mengubah logika bisnis.
Kamu akan mengatur kodemu dalam dua file:
product_repository.dart: File ini berisi entity dan class repository. Mulailah dengan classProductyang memiliki fieldfinaluntukid(int),name(String), danprice(double). Lalu, definisikan abstract classProductRepositoryyang menyatakan kontrak untuk operasi data:getById(int id)yang mengembalikanProductnullable,getAll()yang mengembalikan list produk,save(Product product)untuk menyimpan produk, dandelete(int id)untuk menghapus produk. Terakhir, buatInMemoryProductRepositoryyang mengimplementasikan interface ini menggunakanMap<int, Product>untuk penyimpanan.main.dart: Impor file repository-mu dan tunjukkan pola Repository saat digunakan. BuatInMemoryProductRepository, tetapi simpan dalam variabel bertipeProductRepository. Ini menunjukkan bahwa kodemu bergantung pada interface, 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 dengan formatProducts in stock: [count].
Keunggulan pola ini adalah kode utamamu hanya mengenal interface ProductRepository. Nantinya, kamu bisa membuat DatabaseProductRepository atau ApiProductRepository, lalu 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, harga: 999.99)
// - Mouse (id: 2, harga: 29.99)
// - Keyboard (id: 3, harga: 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