Masukkan Password
66 6.15 What is Factory Constructor in Dart OOP | JSON Parsing with Factory Constructor | Dart Course
Materi kali ini membahas Factory Constructor di Dart. Konsep ini cukup penting karena nanti akan sering kamu temui ketika membuat aplikasi yang mengambil data dari API/JSON, lalu mengubah data tersebut menjadi object Dart.
Saya akan jelaskan dari dasar, termasuk perbedaan constructor biasa dengan factory constructor, fromMap, proses JSON → object, dan kenapa pola ini sangat sering dipakai.
Catatan: beberapa kata di caption salah karena hasil speech-to-text. “DOT” maksudnya Dart, “miine” = mixin, “Json” = JSON, dan sebagainya.
1. Apa itu Factory Constructor?
Sebelumnya kamu sudah belajar constructor biasa.
Contohnya:
class Post {
String title;
String body;
Post(this.title, this.body);
}
Kita membuat object:
var post = Post(
'Judul',
'Isi artikel',
);
Constructor biasa seperti ini disebut generative constructor.
Tugas sederhananya:
Membuat dan menginisialisasi instance baru dari class tersebut.
Sedangkan factory constructor sedikit berbeda.
class Post {
factory Post.fromMap(Map<String, dynamic> map) {
return Post(
map['title'],
map['body'],
);
}
}
Factory constructor memungkinkan kita mengontrol bagaimana object dibuat dan object apa yang dikembalikan.
Materi menjelaskan factory constructor sebagai constructor khusus yang dapat mengembalikan instance yang sudah ada atau instance dari subclass yang berbeda, daripada selalu membuat instance baru.
2. Analogi Sederhana
Bayangkan kamu pergi ke sebuah pabrik.
Kalau kamu berkata:
“Buatkan saya produk.”
Pabrik akan menentukan bagaimana produk itu dibuat.
Factory constructor juga seperti itu.
Data masuk
↓
Factory Constructor
↓
memproses data
↓
Object Dart
Misalnya data dari API:
{
"title": "Hello",
"body": "This is body"
}
Factory constructor akan mengubahnya menjadi:
Post(
'Hello',
'This is body',
)
Jadi salah satu kegunaan paling penting factory constructor adalah:
Mengubah data mentah seperti Map/JSON menjadi object Dart.
3. Constructor Biasa Terlebih Dahulu
Mari kita mulai dari contoh yang ada di materi.
class Post {
String title;
String body;
Post(this.title, this.body);
}
Kemudian:
var post = Post(
'Dummy title',
'Dummy body',
);
Alurnya:
Post(...)
↓
constructor Post
↓
buat object Post
↓
title = Dummy title
body = Dummy body
Ini adalah constructor biasa/generative constructor.
4. Sekarang Kita Punya Data dari Map
Misalnya kita mendapatkan data seperti ini:
Map<String, dynamic> data = {
'title': 'This is title',
'body': 'This is body',
};
Data tersebut bukan object Post.
Data tersebut adalah:
Map
Strukturnya:
data
├── title → This is title
└── body → This is body
Sedangkan yang kita inginkan:
Post object
├── title
└── body
Jadi kita membutuhkan proses:
Map
↓
Post object
Nah, factory constructor sangat cocok untuk melakukan proses tersebut.
5. Membuat Factory Constructor
Kita bisa membuat:
factory Post.fromMap(Map<String, dynamic> map) {
return Post(
map['title'],
map['body'],
);
}
Mari kita pecah.
Bagian pertama
factory
Memberitahu Dart:
Ini adalah factory constructor.
Bagian kedua
Post
Nama class.
Bagian ketiga
.fromMap
Ini adalah named factory constructor.
Namanya bisa saja:
Post.fromMap()
atau:
Post.fromJson()
atau nama lain yang sesuai.
fromMap bukan keyword khusus Dart. Itu hanya nama yang kita pilih untuk menjelaskan bahwa inputnya adalah Map.
6. Kenapa Namanya fromMap?
Karena kita sedang melakukan:
FROM MAP
↓
Post
Contohnya:
Post.fromMap(data);
Artinya secara gampang:
“Buat sebuah Post berdasarkan data Map ini.”
Makanya pola seperti ini sangat populer:
User.fromMap(...)
Product.fromMap(...)
Post.fromMap(...)
atau ketika berhubungan dengan JSON:
User.fromJson(...)
Product.fromJson(...)
Post.fromJson(...)
7. Bagian Map<String, dynamic>
Ini juga perlu kamu pahami.
Kita menulis:
Map<String, dynamic> map
Artinya parameter map adalah Map yang:
- key-nya berupa
String - value-nya boleh bermacam-macam tipe
Contoh:
{
'title': 'Hello',
'body': 'World',
'id': 10,
}
Di sini:
title → String
body → String
id → int
Karena tipe value berbeda-beda, kita menggunakan:
dynamic
Jadi:
Map<String, dynamic>
sangat umum digunakan ketika bekerja dengan data JSON.
8. Bagaimana return Post(...) Bekerja?
Perhatikan:
factory Post.fromMap(Map<String, dynamic> map) {
return Post(
map['title'],
map['body'],
);
}
Ada:
return Post(...)
Artinya factory constructor tersebut mengembalikan object Post.
Misalnya:
var data = {
'title': 'Hello',
'body': 'World',
};
Kemudian:
var post = Post.fromMap(data);
Yang terjadi:
data
↓
Post.fromMap(data)
↓
ambil data['title']
↓
ambil data['body']
↓
Post(title, body)
↓
return object Post
↓
post
Jadi:
post
sekarang merupakan object Post.
9. Contoh Lengkap Sederhana
class Post {
String title;
String body;
Post(this.title, this.body);
factory Post.fromMap(Map<String, dynamic> map) {
return Post(
map['title'],
map['body'],
);
}
}
Kemudian:
void main() {
Map<String, dynamic> data = {
'title': 'Belajar Dart',
'body': 'Belajar Factory Constructor',
};
var post = Post.fromMap(data);
print(post.title);
print(post.body);
}
Output:
Belajar Dart
Belajar Factory Constructor
10. Kenapa Tidak Langsung Saja?
Mungkin kamu berpikir:
“Kenapa harus pakai factory? Bukankah bisa begini?”
var post = Post(
data['title'],
data['body'],
);
Bisa.
Untuk kasus sederhana, memang bisa.
Tetapi bayangkan aplikasi besar.
Misalnya ada:
User
Product
Post
Comment
Category
Order
Transaction
Semuanya menerima data dari API.
Kalau setiap kali kita harus menulis:
User(
data['name'],
data['email'],
data['age'],
);
akan menjadi tidak rapi.
Dengan factory:
User.fromMap(data);
kita memusatkan logika konversi di dalam class User.
Jadi lebih rapi.
11. Inilah Kenapa Factory Banyak Dipakai dengan API
Ini adalah bagian paling penting dari materi.
Ketika aplikasi meminta data ke server:
Flutter/Dart App
↓
HTTP
↓
Server
↓
JSON
Server biasanya mengirim data seperti:
{
"id": 1,
"userId": 1,
"title": "Hello",
"body": "World"
}
Data ini awalnya adalah data JSON, bukan object class Post milik aplikasi kita.
Kita ingin:
JSON
↓
Map
↓
Post object
Factory constructor bisa menjadi tempat untuk melakukan konversi tersebut.
12. JSON dan Map Itu Sama?
Dalam caption, instruktur beberapa kali menyebut JSON dan Map secara bergantian.
Untuk pemahaman pemula, kita perlu membedakannya sedikit.
JSON adalah format data.
Contoh JSON:
{
"title": "Hello",
"body": "World"
}
Sedangkan di Dart kita sering bekerja dengan:
Map<String, dynamic>
yang bentuknya mirip:
{
'title': 'Hello',
'body': 'World',
}
Jadi konsep sederhananya:
JSON dari server
↓
decode JSON
↓
Map<String, dynamic>
↓
Post.fromMap()
↓
Post object
Proses mengubah data JSON menjadi object aplikasi sering disebut JSON parsing / deserialization.
13. Contoh Data yang Lebih Lengkap
Materi kemudian menambahkan:
int id;
int userId;
String title;
String body;
Jadi class:
class Post {
int id;
int userId;
String title;
String body;
Post(
this.id,
this.userId,
this.title,
this.body,
);
factory Post.fromMap(Map<String, dynamic> map) {
return Post(
map['id'],
map['userId'],
map['title'],
map['body'],
);
}
}
Sekarang data:
Map<String, dynamic> data = {
'id': 1,
'userId': 1,
'title': 'Hello',
'body': 'This is body',
};
Kita cukup:
var post = Post.fromMap(data);
Kemudian:
print(post.id);
print(post.userId);
print(post.title);
print(post.body);
14. Yang Terjadi di Dalam fromMap
Perhatikan:
factory Post.fromMap(Map<String, dynamic> map) {
return Post(
map['id'],
map['userId'],
map['title'],
map['body'],
);
}
Sebenarnya factory ini melakukan pekerjaan:
map['id']
↓
Post.id
map['userId']
↓
Post.userId
map['title']
↓
Post.title
map['body']
↓
Post.body
Jadi factory adalah semacam jembatan:
Map ───────────────→ Post
fromMap()
15. Sekarang Bayangkan Ada 100 Post
Ini bagian yang menarik dari contoh materi.
Misalnya server mengirim:
100 post
Data bisa berupa:
List<Map<String, dynamic>>
Misalnya:
final data = [
{
'id': 1,
'userId': 1,
'title': 'Title 1',
'body': 'Body 1',
},
{
'id': 2,
'userId': 1,
'title': 'Title 2',
'body': 'Body 2',
},
];
Kita ingin mengubahnya menjadi:
List<Post>
16. Membuat List Post
Kita bisa membuat:
List<Post> posts = [];
Artinya:
Buat list kosong yang hanya boleh berisi object
Post.
Awalnya:
posts
↓
[]
17. Melakukan Loop pada Data
Kemudian kita iterasi data:
data.forEach((element) {
posts.add(
Post.fromMap(element),
);
});
Mari kita lihat apa yang terjadi.
Data pertama:
{
'id': 1,
'userId': 1,
'title': 'Title 1',
'body': 'Body 1',
}
diproses:
Post.fromMap(element)
menjadi:
Post object #1
kemudian:
posts.add(...)
memasukkannya ke list.
Kemudian data kedua:
Map #2
↓
Post.fromMap()
↓
Post object #2
↓
posts.add()
Dan seterusnya.
18. Gambaran Keseluruhan
Prosesnya:
DATA DARI API
│
↓
List<Map<String,dynamic>>
│
↓
forEach()
│
┌────────┴────────┐
↓ ↓
element 1 element 2
↓ ↓
Post.fromMap() Post.fromMap()
↓ ↓
Post #1 Post #2
│ │
└────────┬────────┘
↓
List<Post>
Ini adalah pola yang sangat penting dalam aplikasi yang berkomunikasi dengan API.
19. Kenapa posts.length Menjadi 100?
Misalnya server memberikan 100 data.
Kita melakukan:
List<Post> posts = [];
data.forEach((element) {
posts.add(Post.fromMap(element));
});
Setiap satu element menghasilkan satu object Post.
Maka:
100 Map
↓
100 Post object
↓
List<Post> berisi 100 object
Jadi:
print(posts.length);
menghasilkan:
100
Materi menggunakan hasil 100 ini sebagai verifikasi bahwa seluruh data berhasil dikonversi ke object Post.
20. Mengakses Data Post Pertama
Setelah:
List<Post> posts = [];
berisi object-object Post, kita tidak lagi bekerja dengan Map.
Kita sudah bekerja dengan:
Post
Misalnya:
print(posts.first.title);
Artinya:
posts
↓
ambil object pertama
↓
.first
↓
ambil property title
↓
.title
Misalnya output:
Title 1
Kemudian:
print(posts.first.body);
hasil:
Body 1
Jadi sekarang data sudah menjadi object Dart yang bisa kita gunakan seperti object biasa.
21. Perbedaan Sebelum dan Sesudah Parsing
Sebelum parsing
Kita memiliki:
Map<String, dynamic>
Akses:
data['title']
Setelah parsing
Kita memiliki:
Post
Akses:
post.title
Ini perbedaan yang sangat penting.
SEBELUM
Map
↓
data['title']
SESUDAH
Post
↓
post.title
Object-oriented programming menjadi lebih nyaman karena kita bisa menggunakan property dan method yang didefinisikan dalam class.
22. Kenapa Post.fromMap() Lebih Bagus?
Bandingkan.
Tanpa factory:
var post = Post(
data['id'],
data['userId'],
data['title'],
data['body'],
);
Dengan factory:
var post = Post.fromMap(data);
Yang kedua lebih jelas.
Ketika programmer melihat:
Post.fromMap(data)
langsung terlihat:
“Oh, data Map ini sedang dikonversi menjadi Post.”
Itulah salah satu alasan pola fromMap/fromJson sangat populer.
23. Factory Constructor Bukan Hanya fromMap
Nama fromMap sebenarnya bukan kewajiban.
Kita bisa membuat:
factory Post.fromJson(...) {
}
atau:
factory Post.fromDatabase(...) {
}
atau:
factory Post.fromResponse(...) {
}
Contohnya:
factory Post.fromMap(Map<String, dynamic> map) {
...
}
Nama fromMap dipilih karena inputnya Map.
Kalau inputnya JSON string, biasanya kita bisa menggunakan nama:
fromJson
24. Kapan Factory Constructor Berguna?
Dari materi, penggunaan yang paling ditekankan adalah konversi data API/JSON menjadi object Dart.
Tetapi secara konsep factory juga berguna ketika kita ingin mengontrol pembuatan object.
Contohnya:
1. Parsing Map/JSON
Post.fromMap(data)
2. Memilih object tertentu
Factory dapat menentukan object apa yang dikembalikan.
3. Menggunakan kembali instance tertentu
Sesuai definisi factory, constructor ini dapat mengembalikan instance yang sudah ada daripada selalu membuat object baru.
4. Menyembunyikan logika pembuatan object
Daripada caller harus tahu bagaimana object dibuat:
Post.fromMap(data)
cukup digunakan.
25. Constructor Biasa vs Factory Constructor
Ini bagian yang harus benar-benar kamu kuasai.
| Constructor biasa | Factory constructor |
|---|---|
| Generative constructor | Factory constructor |
| Biasanya membuat instance baru | Dapat mengontrol instance yang dikembalikan |
| Bisa menginisialisasi instance secara langsung | Bisa menjalankan logic sebelum menentukan object yang dikembalikan |
Tidak menggunakan factory | Menggunakan factory |
Contoh Post(...) | Contoh Post.fromMap(...) |
Contoh constructor biasa:
Post(this.title, this.body);
Contoh factory:
factory Post.fromMap(Map<String, dynamic> map) {
return Post(
map['title'],
map['body'],
);
}
26. Factory Tidak Harus return Post(...)?
Nah, secara konsep tidak harus selalu mengembalikan object dari class yang sama.
Inilah salah satu kemampuan factory constructor.
Misalnya sebuah factory dapat menentukan instance yang akan dikembalikan berdasarkan kondisi tertentu.
Konsepnya:
factory SomeClass(...) {
if (condition) {
return SomeClassA(...);
}
return SomeClassB(...);
}
Jadi factory bisa bertindak sebagai pengambil keputusan dalam proses pembuatan object.
Namun dalam contoh materi ini, factory digunakan secara sederhana untuk:
Map → Post
dan bukan untuk memilih subclass.
27. Hal yang Sangat Penting: Factory Bisa Memiliki Logic
Constructor biasa memang bisa melakukan initialization, tetapi factory sangat berguna ketika proses pembuatan membutuhkan logic.
Misalnya secara konsep:
factory User.fromMap(Map<String, dynamic> map) {
if (map['role'] == 'admin') {
return AdminUser(...);
}
return NormalUser(...);
}
Artinya caller cukup:
User.fromMap(data);
Factory yang menentukan object sebenarnya.
Jadi:
Factory constructor bisa menjadi “pintu masuk” untuk proses pembuatan object.
28. Hubungan Factory dengan API
Ini mungkin bagian paling penting untuk kamu sebagai programmer Flutter/Dart.
Nanti ketika belajar HTTP/API, kamu akan sering melihat alur seperti ini:
SERVER
│
│ HTTP Response
↓
JSON
│
↓
Map<String, dynamic>
│
↓
Model.fromJson()
│
↓
Dart Object
│
↓
UI
Misalnya:
final post = Post.fromMap(jsonData);
Kemudian UI bisa menggunakan:
Text(post.title)
atau:
Text(post.body)
Jadi factory constructor sering menjadi bagian dari model class.
29. Contoh Model yang Lebih Realistis
Misalnya:
class User {
final int id;
final String name;
final String email;
User({
required this.id,
required this.name,
required this.email,
});
factory User.fromMap(Map<String, dynamic> map) {
return User(
id: map['id'],
name: map['name'],
email: map['email'],
);
}
}
Kemudian:
final data = {
'id': 1,
'name': 'Budi',
'email': 'budi@example.com',
};
Kita tinggal:
final user = User.fromMap(data);
Sekarang:
print(user.name);
hasil:
Budi
30. Pola yang Perlu Kamu Hafalkan
Untuk sekarang, kamu cukup mengingat pola ini:
class Post {
String title;
String body;
Post(this.title, this.body);
factory Post.fromMap(Map<String, dynamic> map) {
return Post(
map['title'],
map['body'],
);
}
}
Kemudian:
final post = Post.fromMap(data);
Pola tersebut berarti:
Map
↓
fromMap()
↓
Post
31. Ada Satu Detail Penting tentang factory
Jangan berpikir:
“
factoryadalah constructor yang otomatis mengubah JSON.”
Bukan begitu.
factory sendiri tidak otomatis tahu JSON.
Kitalah yang menulis logic-nya:
factory Post.fromMap(Map<String, dynamic> map) {
return Post(
map['title'],
map['body'],
);
}
Jadi factory hanyalah mekanisme constructor khusus.
Kita sendiri yang menentukan:
input apa?
logic apa?
object apa yang dikembalikan?
Itulah yang membuatnya powerful.
32. Analogi Terakhir: Restoran
Bayangkan kamu pergi ke restoran.
Kamu pesan:
"Menu Post dari data ini."
Kamu sebagai customer tidak perlu tahu bagaimana dapur membuatnya.
Kamu cukup:
Post.fromMap(data)
Di dalamnya:
fromMap()
↓
ambil title
↓
ambil body
↓
buat Post
↓
return Post
Jadi factory constructor seperti dapur yang menangani proses pembuatan object.
33. Kesimpulan
Materi ini sebenarnya ingin mengajarkan satu pola yang sangat penting:
DATA MENTAH
↓
Map / JSON
↓
Factory Constructor
↓
Dart Object
Contoh:
final post = Post.fromMap(data);
Setelah itu:
post.title
post.body
post.id
post.userId
bisa digunakan seperti object Dart biasa.
Ingat 6 poin ini:
Constructor biasa biasanya digunakan untuk membuat object secara langsung.
Factory constructor menggunakan keyword:
factoryFactory dapat mempunyai nama seperti:
Post.fromMap()fromMapadalah pola penamaan yang berarti:“Buat object berdasarkan data Map.”
Factory sangat berguna ketika bekerja dengan:
API → JSON → Map → Object DartJika ada banyak data:
List<Map> ↓ Post.fromMap() berkali-kali ↓ List<Post>
Kalau materi Mixin sebelumnya bisa kamu pahami sebagai “menambahkan kemampuan ke class”, maka materi Factory Constructor ini bisa kamu pahami sebagai “mengatur bagaimana object dibuat, terutama dari data mentah seperti Map/JSON.”