Pola Composite
Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan GO di Coddy. Pelajaran 96 dari 107.
Pola Composite memungkinkan kamu memperlakukan object individual dan grup object secara seragam. Sementara State mengubah perilaku berdasarkan state internal, Composite membangun struktur pohon yang membuat daun dan wadah menggunakan antarmuka yang sama.
Pola ini sangat cocok untuk struktur hierarkis seperti sistem file, bagan organisasi, atau komponen UI. Di Go, kita mendefinisikan interface umum yang diimplementasikan oleh item individual dan kontainer:
type Component interface {
GetSize() int
}
type File struct {
Name string
Size int
}
func (f File) GetSize() int {
return f.Size
}Komponen komposit (wadah) menampung komponen anak dan menerapkan antarmuka yang sama dengan menggabungkan hasilnya:
type Folder struct {
Name string
Children []Component
}
func (f *Folder) Add(c Component) {
f.Children = append(f.Children, c)
}
func (f Folder) GetSize() int {
total := 0
for _, child := range f.Children {
total += child.GetSize()
}
return total
}Sekarang kamu bisa membuat folder bersarang di dalam folder lain, dan memanggil GetSize() bekerja dengan cara yang sama, baik untuk satu file maupun seluruh pohon direktori:
docs := &Folder{Name: "docs"}
docs.Add(File{Name: "readme.txt", Size: 100})
docs.Add(File{Name: "notes.txt", Size: 50})
root := &Folder{Name: "root"}
root.Add(docs)
root.Add(File{Name: "config.json", Size: 25})
fmt.Println(root.GetSize()) // 175Composite cocok digunakan saat kamu perlu merepresentasikan hierarki bagian-keseluruhan dan ingin client memperlakukan object individual dan komposisi secara sama.
Tantangan
MudahMari buat sistem bagan organisasi menggunakan pola Composite! Kamu akan membuat struktur tempat setiap karyawan dan departemen (yang berisi karyawan atau departemen lain) dapat diperlakukan secara seragam, cocok untuk menghitung total gaji di bagian mana pun dalam organisasi.
Kamu akan mengatur kodemu dalam tiga file:
component.go: Definisikan interface umum yang akan diterapkan oleh setiap individu dan kelompok.Buat interface
OrgComponentdengan dua method:GetSalary() int: mengembalikan total gaji untuk komponen iniGetName() string: mengembalikan nama karyawan atau departemen
organization.go: Implementasikan tipe leaf (karyawan individu) dan composite (departemen).Buat struct
Employeedengan fieldName(string) danSalary(int).GetSalary()mengembalikan gajinya sendiri, danGetName()mengembalikan namanya.Buat struct
Departmentdengan fieldName(string) dan sliceMembersyang menampung itemOrgComponent. Tambahkan methodAdd(c OrgComponent)untuk menambahkan anggota.GetSalary()harus mengembalikan jumlah gaji semua anggotanya, danGetName()mengembalikan nama departemen.main.go: Bangun struktur organisasi dan hitung gaji.Baca jumlah karyawan. Untuk setiap karyawan, baca nama dan gajinya, lalu buat instance
Employee. Kemudian baca jumlah departemen. Untuk setiap departemen, baca namanya dan jumlah indeks anggota, lalu baca indeks-indeks tersebut (berbasis 0, merujuk pada karyawan atau departemen yang sudah dibuat sebelumnya sesuai urutan pembuatannya).Setelah membangun struktur, baca indeks terakhir dan cetak nama komponen tersebut serta total gajinya dengan format:
[name]: [salary]
Input berikut akan diberikan:
- Jumlah karyawan, lalu nama dan gaji setiap karyawan pada baris terpisah
- Jumlah departemen, lalu nama setiap departemen, jumlah anggota, dan indeks anggota
- Indeks terakhir untuk dikueri
Contohnya, jika diberikan:
3
Alice
50000
Bob
60000
Carol
55000
1
Engineering
3
0
1
2
3Outputmu harus berupa:
Engineering: 165000Dan jika diberikan:
4
Alice
50000
Bob
60000
Carol
55000
Dave
70000
2
Dev
2
0
1
QA
2
2
3
4Outputmu harus berupa:
QA: 125000Dan jika diberikan:
2
Alice
50000
Bob
60000
0
1Outputmu harus berupa:
Bob: 60000Perhatikan bahwa GetSalary() bekerja dengan cara yang sama, baik saat kamu memanggilnya pada satu karyawan maupun pada seluruh departemen: pola Composite memungkinkan kamu memperlakukan individu dan kelompok secara seragam melalui interface yang sama!
Coba sendiri
package main
import "fmt"
func main() {
// Baca jumlah karyawan
var numEmployees int
fmt.Scanln(&numEmployees)
// Simpan semua komponen (karyawan dan departemen) sesuai urutan pembuatannya
var components []OrgComponent
// TODO: Baca nama dan gaji setiap karyawan
// Buat instance Employee dan tambahkan ke slice components
for i := 0; i < numEmployees; i++ {
var name string
var salary int
fmt.Scanln(&name)
fmt.Scanln(&salary)
// TODO: Buat karyawan dan tambahkan ke components
}
// Baca jumlah departemen
var numDepartments int
fmt.Scanln(&numDepartments)
// TODO: Baca nama, jumlah anggota, dan indeks anggota setiap departemen
// Buat instance Department, tambahkan anggota berdasarkan indeks, lalu tambahkan ke components
for i := 0; i < numDepartments; i++ {
var deptName string
var memberCount int
fmt.Scanln(&deptName)
fmt.Scanln(&memberCount)
// TODO: Buat departemen, baca indeks anggota, tambahkan anggota, lalu tambahkan ke components
}
// Baca indeks terakhir untuk query
var queryIndex int
fmt.Scanln(&queryIndex)
// TODO: Cetak nama komponen dan total gajinya dalam format: [name]: [salary]
// Contoh: fmt.Printf("%s: %d\n", name, salary)
}
Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.
Semua pelajaran di Pemrograman Berorientasi Objek
1Dasar-Dasar OOP di Go
File EksternalWorkspace Go dan modulePaket dan ImporNama yang Diekspor dan Tidak DieksporPengantar OOP di Gostruct sebagai classMendefinisikan method pada structPointer receiver vs value receiverInisialisasi structFungsi KonstruktorUlasan: Kalkulator Sederhana4Interface
Pengenalan InterfaceImplementasi ImplisitInterface sebagai KontrakInterface Kosong (any)Type AssertionType SwitchKomposisi InterfaceInterface Stringer & ErrorUlasan: Kalkulator Bentuk7Enkapsulasi
Field yang Diekspor vs Tidak DieksporEnkapsulasi Tingkat PackageMethod Getter dan SetterPenyembunyian Informasi di GoRingkasan: Data Siswa10Generics (Go 1.18+)
Pengantar GenericsParameter TipeBatasan TipeStruct GenerikCara Alternatif untuk Method GenerikRingkasan Koleksi Generik2Mendalami Tipe dan Struct
Tipe Dasar dan KompositDefinisi Tipe KustomTag StructStruct AnonimStruct BersarangNilai Nol dan Nilai BawaanRangkuman: Buku Kontak5Komposisi daripada Pewarisan
Mengapa Go Tidak Memiliki PewarisanDasar Penyematan StructPromosi methodMenyematkan Beberapa StructPenyematan vs AgregasiMembayangi method yang DisematkanRangkuman: Hierarki Karyawan8Penanganan Error & OOP
Interface errorTipe Error KustomPembungkusan Error (fmt.Errorf)Error Sentinelerrors.Is() dan errors.As()Panic, Defer, dan RecoverRangkuman: Parser File11Pustaka Standar & OOP
io.Reader & io.Writersort.InterfaceAntarmuka fmt.Stringerencoding/json dengan StructAntarmuka http.HandlerRingkasan, Model REST API14Pola Desain Bagian 2
Pola CommandPola AdapterPola DecoratorPola Template MethodPola StatePola CompositeMiddleware sebagai Decorator3Pointer dan Memori
Dasar-Dasar Pointer di GoPointer ke StructPass by Value vs ReferenceFungsi new()Garbage Collection di GoRekap: Pembuat Linked List6Polimorfisme di Go
Polimorfisme melalui InterfaceDuck Typing di GoAturan Pemenuhan InterfaceKoleksi PolimorfikInjeksi DependensiRangkuman: Pemroses Pembayaran9Konkruensi & OOP
Dasar-dasar GoroutineChannel & KomunikasiChannel Ber-buffer vs Tanpa BufferPernyataan selectsync.Mutex & sync.RWMutexsync.WaitGroupDesain Struct yang Aman untuk ThreadRingkasan: Worker PoolLatihan sendiri: Compiler Go online