- Published on
Chain of Responsibility dengan Golang
- Authors
- Name
- Aulia' Illahi
- @alfath_go
- Name
Definisi
Chain of Responsibility design pattern adalah turunan dari Behavioral Design Pattern. Pattern ini membuat pola rantai pada request. mengaitkan setiap permintaan kedalam rantai request . Alur dari proses pengikatan request tersebut sebagai berikut:
- Proses request atau skip proses.
- Menentukan apakah proses dapat dilanjutkan ke handler berikutnya atau tidak.
Design pattern ini akan mudah untuk difahami jika menggunakan contoh studi kasus. studi kasus diambil dengan sesederhana mungkin dengan tujuan untuk menjelaskan secara sederhana konsep design pattern chain of responsibility, contoh kasusnya adalah Dalam pengecekan alur pembayaran paylater. Sistem pembayaran paylater memiliki skema alur:
- Check Status pengguna (Eligibility Checker)
- Check limit paylater (Limit Checker)
- Payment Processor
Contoh kasusnya: Ada 3 pengguna ingin melakukan pembelian barang:
- Udin berumur 25 tahun, dengan credit limit 500 rb, dan akan membeli barang 300 rb.
- Budi berumur 16 tahun, dengan credit limit 700 rb, dan akan membeli barang 200 rb.
- Eno berumur 19 tahun, dengan credit limit 700 rb, dan akan membeli barang 900 rb.
Alur pembayaran akan melalui beberapa langkah yang pertama Check status akun paylater pengguna, kemudian check limit paylater pengguna, selanjutanya jika sesuai sistem akan melakukan Payment Process ke pengguna. dan pembayaran transaksi berhasil.

dari UML tersebut akan mempermudah kita mempraktekannya dalam bentuk kode program:
- Paylater Handler interface (paylater_hadler.go)
- Eligible Check (eligible_handler.go)
- Limit Check (limit_handler.go)
- Payment Process (payment_process_handler.go)
- User Model (user.go)
- Client (main.go)
Langsung coba kita implementasi kedalam kode program
paylater_hadler.go
package main
// PayLaterHandler interface defines the handle_request method
type PayLaterHandler interface {
handleRequest(user *User)
setSuccessor(successor PayLaterHandler)
}
// BaseHandler is a base implementation of PayLaterHandler
type BaseHandler struct {
successor PayLaterHandler
}
func (h *BaseHandler) setSuccessor(successor PayLaterHandler) {
h.successor = successor
}
eligible_handler.go
package main
import "fmt"
// EligibilityChecker checks if the user is eligible for paylater
type EligibilityChecker struct {
BaseHandler
}
func (ec *EligibilityChecker) handleRequest(user *User) {
if user.Age <= 18 {
fmt.Printf("User %s is not eligible for paylater.\n", user.Name)
} else if ec.successor != nil {
ec.successor.handleRequest(user)
}
}
limit_handler.go
package main
import "fmt"
// LimitChecker checks if the credit limit is sufficient
type LimitChecker struct {
BaseHandler
}
func (lc *LimitChecker) handleRequest(user *User) {
if user.CreditLimit <= user.PurchaseAmount {
fmt.Printf("Credit limit user %s is insufficient.\n", user.Name)
} else if lc.successor != nil {
lc.successor.handleRequest(user)
}
}
payment_process_handler.go
package main
import "fmt"
// PaymentProcessor processes the paylater payment
type PaymentProcessor struct {
BaseHandler
}
func (pp *PaymentProcessor) handleRequest(user *User) {
fmt.Printf("Processing paylater payment for %s.\n", user.Name)
}
// ProcessPayLater initiates the paylater processing chain
func ProcessPayLater(user *User, handler PayLaterHandler) {
handler.handleRequest(user)
}
user.go
package main
// User struct represents a user with relevant information
type User struct {
Name string
Age int
CreditLimit int
PurchaseAmount int
}
main.go
package main
import "fmt"
func main() {
// Create user instances
user1 := &User{Name: "Udin", Age: 25, CreditLimit: 500, PurchaseAmount: 300}
user2 := &User{Name: "Budi", Age: 16, CreditLimit: 700, PurchaseAmount: 200}
user3 := &User{Name: "Eno", Age: 19, CreditLimit: 700, PurchaseAmount: 900}
// Create the chain of handlers
paymentProcessor := &PaymentProcessor{}
eligibilityChecker := &EligibilityChecker{BaseHandler{successor: paymentProcessor}}
limitChecker := &LimitChecker{BaseHandler{successor: eligibilityChecker}}
limitChecker.setSuccessor(eligibilityChecker)
eligibilityChecker.setSuccessor(paymentProcessor)
fmt.Println(" ")
ProcessPayLater(user1, limitChecker)
ProcessPayLater(user2, limitChecker)
ProcessPayLater(user3, limitChecker)
}
Output
