โ Kembali ke Design Pattern
๐ณ
Structural
Composite
Menyusun objek menjadi struktur tree dan membuat client bisa memperlakukan objek tunggal maupun gabungannya dengan cara yang sama.
Masalahnya
Kamu punya hierarki tree (komponen UI, file system, bagan organisasi) di mana operasi harus bekerja sama persis pada leaf maupun container, tanpa kasus khusus di kode client.
Cara Kerja
- โบLeaf dan Composite berbagi interface yang sama, client tidak perlu pengecekan instanceof
- โบStruktur rekursif: container bisa berisi leaf maupun container lain
- โบMenyederhanakan kode client yang bekerja dengan struktur tree
- โบMudah menambahkan jenis komponen baru tanpa mengubah kode client
- โบBisa terlalu umum saat kamu butuh batasan tentang apa yang boleh menyusun apa
Kapan Digunakan
โTree komponen UI, tree file system, bagan organisasi, hierarki menu
โSaat kode client harus memperlakukan item tunggal dan grup secara identik
โHierarki part-whole apa pun yang bersifat rekursif
โMe-render komponen bersarang secara seragam
Contoh di Dunia Nyata
๐
iOS
UIView hierarchy (every UIView can contain child views), SwiftUI View tree
๐ค
Android
ViewGroup containing Views and other ViewGroups, Jetpack Compose UI tree
๐
Web
DOM tree, React component tree, virtual DOM diffing
Contoh Kode
Swift
protocol UIComponent {
var name: String { get }
func render(indent: String)
}
class UILeaf: UIComponent {
let name: String
init(_ name: String) { self.name = name }
func render(indent: String = "") { print("\(indent)[\(name)]") }
}
class UIContainer: UIComponent {
let name: String
private var children = [UIComponent]()
init(_ name: String) { self.name = name }
func add(_ child: UIComponent) { children.append(child) }
func render(indent: String = "") {
print("\(indent)<\(name)>")
children.forEach { $0.render(indent: indent + " ") }
}
}
let screen = UIContainer("Screen")
let header = UIContainer("Header")
header.add(UILeaf("Logo")); header.add(UILeaf("NavTitle"))
screen.add(header)
screen.add(UILeaf("HeroImage"))
screen.add(UILeaf("CTAButton"))
screen.render()
// <Screen>
// <Header>
// [Logo]
// [NavTitle]
// [HeroImage]
// [CTAButton]