Artikel Ini adalah lanjutan pembahasan implementasi design-pattern yang sebelumnya dibahas pada Bersolek Ria dengan Decorator-pattern. Domain permasalah dan sources code yang digunakan merupakan lanjutan dari pembahasan sebelumnya.
Prolog
Perusahaan tempat anda bekerja ternyata memiliki segudang ide dan rencana terkait dengan aplikasi yang anda kelola. Hari ini anda, atasan anda dan seorang product owner melakukan virtual meeting terkait enhancement dari aplikasi tersebut. Diskusi berakhir dengan sebuah tugas yang di bebankan kepada anda melalui atasan anda.
Anda diminta untuk menambahkan fungsi untuk memfilter setiap pegawai yang akan dikirimkan notifikasi peringatan ke sources code yang ada. Saat ini aplikasi anda bersifat "buta" dengan mengirimkan notifikasi peringatan kepada seluruh pegawai di setiap level tanpa memperhatikan apakah status pegawai tersebut masih aktif atau tidak.
Open for extension Closed for modification
Atasan anda meminta agar filter yang dibuat bisa digunakan dimanapun ketika ada fitur yang membutuhkan. Filter tersebut juga diharapkan nantinya tidak perlu dimodifikasi apabila ada kebutuhan untuk memfilter pegawai dengan cara yang berbeda. Atasan anda kemudian menyebut sebuah kata yang bisa mengubah hidup anda sepenuhnya, dia berkata
"Coba pelajari iterator pattern"
Iterator
Setelah mendapatkan petunjuk dari atasan anda, anda memutuskan untuk menggunakan iterator pattern pada kasus ini. Anda berencana untuk membuat sebuah objek yang hanya bertanggung jawab untuk memfilter status aktif dari pegawai. Anda juga tahu bahwa dengan menggunakan pattern ini iterator lain bisa dengan mudah ditambahkan apabila nanti dibutuhkan.
iterator.go
type Iterator interface {
GetNext() Employee
HasMore() bool
}
active_employee_iterator.go
type ActiveEmployeeIterator struct {
Employees []entity.Employee
CurrentPosition int
Status bool
}
func (iter *ActiveEmployeeIterator) GetNext() entity.Employee {
if !iter.HasMore() {
return nil
}
employee := iter.Employees[iter.CurrentPosition]
iter.CurrentPosition++
if employee.GetStatus() {
return employee
}
return iter.GetNext()
}
func (iter *ActiveEmployeeIterator) HasMore() bool {
if iter.CurrentPosition >= len(iter.Employees) {
return false
}
employee := iter.Employees[iter.CurrentPosition]
if employee.GetStatus() {
return iter.CurrentPosition < len(iter.Employees)
}
iter.CurrentPosition++
return iter.HasMore()
}
func NewActiveEmployeeIterator(employees []entity.Employee, status bool) *ActiveEmployeeIterator {
return &ActiveEmployeeIterator{Employees: employees, Status: status}
}
Panggil iterator pada main program sehingga;
main.go
// iterate only for active employee
employeesIter := iterator.NewActiveEmployeeIterator(employees, true)
for employeesIter.HasMore() {
employee := employeesIter.GetNext()
// accept performance notification visitor
employee.Accept(performanceNotification)
// accept bonus income visitor
employee.Accept(bonusIncome)
}
Epilog
Seluruh sources code yang berkaitan dengan artikel ini dapat dilihat pada repository berikut https://github.com/Mhakimamransyah/practice-design-pattern
Referensi Bacaan
https://refactoring.guru/design-patterns/iterator
Author
https://github.com/Mhakimamransyah
https://www.linkedin.com/in/hakim-amr/
mailto: m.hakim.amransyah.hakim@gmail.com
Top comments (0)