- vừa được xem lúc

[ Design Patterns ] - Decorator pattern with Golang

0 0 12

Người đăng: Nguyen Van Tuan

Theo Viblo Asia

Ha Noi, on Thursday 30/08/2023

At the moment, a little speech to give to the present...

The cafe, the cigarette, and some rainy days...

Listening to this song, I miss the memories of when we were young, stupid children, and we still loved. When the cafe has no sugar, I often drink something that is sweet. Now, it has a pale taste, like water, or if it has a taste, then the taste is the memories or the regret of all the great old days.

I. Decorator pattern

Decorator is a structural design pattern that lets you attach new behaviors to objects by placing these objects inside special wrapper objects that contain the behaviors.

Using decorators you can wrap objects countless number of times since both target objects and decorators follow the same interface. The resulting object will get a stacking behavior of all wrappers.

Reference: Decorator pattern

II. Implement

image.png

1. The problem

We need to build a system for the notification when the user has the action: create an account, update an account, or delete an account,... and for each action, we will send the notification to some platforms, eg: Slack, SMS, Facebook,...

Example:

  • When a user creates an account. The system will send the notification to the user's phone by SMS.

  • When a user updates the user's account, eg: password, and name,... then we will send the notification to your SMS, your Facebook, and our Slack.

  • When a user deletes the user's account then we will send the notification to your SMS, our Slack.

Note: The system will have a lot of actions and platforms to receive notifications. For each action, we must send a lot of platforms.

2. Problem solving

image.png

When we have a new action and will send the notification to some platforms. We tried to address that problem by creating special subclasses which combined several notification methods within one class. However, it quickly became apparent that this approach would bloat the code immensely, not only the library code but the client code as well.

So, to resolve the problem, we will use the decorator design pattern.

3. Implement decorator design pattern

3.1. Component

package component type INotifier interface { SendNotification(msg string)
}

3.2. Concrete component

This is a folder that handles common logic, eg: getting common information from the database, config, or some common action,...

package concrete_component import ( "fmt" "time"
) type Notifier struct {
} func (n *Notifier) SendNotification(msg string) { fmt.Println("Handle process logic common...") time.Sleep(2 * time.Second)
}

3.3. Concrete decorator

This is a folder that handles and implements sending the notification to each platform, eg: Slack notification, SMS notification, and Facebook notification,...

package concrete_decorator import ( "fmt" "time" "design-pattern-golang-example/decorator-pattern/component"
) type FacebookNotifier struct { Notifier component.INotifier
} func (f *FacebookNotifier) SendNotification(msg string) { f.Notifier.SendNotification(msg) fmt.Println(fmt.Sprintf("Send the notification to Facebook with message %s", msg)) time.Sleep(2 * time.Second) fmt.Println("Done")
}
package concrete_decorator import ( "fmt" "time" "design-pattern-golang-example/decorator-pattern/component"
) type SlackNotifier struct { Notifier component.INotifier
} func (s *SlackNotifier) SendNotification(msg string) { s.Notifier.SendNotification(msg) fmt.Println(fmt.Sprintf("Send the notification to Slack with message %s", msg)) time.Sleep(2 * time.Second) fmt.Println("Done")
}
package concrete_decorator import ( "fmt" "time" "design-pattern-golang-example/decorator-pattern/component"
) type SmsNotifier struct { Notifier component.INotifier
} func (s *SmsNotifier) SendNotification(msg string) { s.Notifier.SendNotification(msg) fmt.Println(fmt.Sprintf("Send the notification to SMS with message %s", msg)) time.Sleep(2 * time.Second) fmt.Println("Done")
}

3.4. Main function and the result

package main import ( "fmt" "time" concreteComponent "design-pattern-golang-example/decorator-pattern/concrete-component" concreteDecorator "design-pattern-golang-example/decorator-pattern/concrete-decorator"
) func main() { // If you create your account then we will send the notification to your SMS CreateAccount("Tuan Nguyen") // If you update your account, eg: password, name,... then we will send the notification to your SMS, your Facebook and our Slack UpdateAccount("Tuan Nguyen") // If you delete your account then we will send the notification to your SMS, our Slack DeleteAccount("Tuan Nguyen")
} func CreateAccount(name string) { fmt.Println(fmt.Sprintf("Create the account with name %s is done.", name)) time.Sleep(2 * time.Second) fmt.Println("Begin to send the notification...") time.Sleep(2 * time.Second) notifier := &concreteComponent.Notifier{} // add sms notification sms := &concreteDecorator.SmsNotifier{ Notifier: notifier, } // send the notification sms.SendNotification("create account")
} func UpdateAccount(name string) { fmt.Println(fmt.Sprintf("Update the account with name %s is done.", name)) time.Sleep(2 * time.Second) fmt.Println("Begin to send the notification...") time.Sleep(2 * time.Second) notifier := &concreteComponent.Notifier{} // add sms notification sms := &concreteDecorator.SmsNotifier{Notifier: notifier} // add facebook notification facebookSMS := &concreteDecorator.FacebookNotifier{Notifier: sms} // add Slack notification slackFacebookSMS := &concreteDecorator.SlackNotifier{Notifier: facebookSMS} // send the notification slackFacebookSMS.SendNotification("update account")
} func DeleteAccount(name string) { fmt.Println(fmt.Sprintf("Delete the account with name %s is done.", name)) time.Sleep(2 * time.Second) fmt.Println("Begin to send the notification...") time.Sleep(2 * time.Second) notifier := &concreteComponent.Notifier{} // add sms notification sms := &concreteDecorator.SmsNotifier{Notifier: notifier} // add Slack notification slackSMS := &concreteDecorator.SlackNotifier{Notifier: sms} // send the notification slackSMS.SendNotification("delete account")
}

The result:

Create an account

Create the account with name Tuan Nguyen is done.
Begin to send the notification...
Handle process logic common...
Send the notification to SMS with message create account
Done

Update an account

Begin to send the notification...
Handle process logic common...
Send the notification to SMS with message update account
Done
Send the notification to Facebook with message update account
Done
Send the notification to Slack with message update account
Done

Delete an account

Delete the account with name Tuan Nguyen is done.
Begin to send the notification...
Handle process logic common...
Send the notification to SMS with message delete account
Done
Send the notification to Slack with message delete account
Done

III. Source code

Bình luận

Bài viết tương tự

- vừa được xem lúc

gRPC - Nó là gì và có nên sử dụng hay không?

Nhân một ngày rảnh rỗi, mình ngồi đọc lại RPC cũng như gRPC viết lại để nhớ lâu hơn. Vấn đề là gì và tại sao cần nó .

0 0 131

- vừa được xem lúc

Embedded Template in Go

Getting Start. Part of developing a web application usually revolves around working with HTML as user interface.

0 0 56

- vừa được xem lúc

Tạo Resful API đơn giản với Echo framework và MySQL

1. Giới thiệu.

0 0 60

- vừa được xem lúc

Sử dụng goquery trong golang để crawler thông tin các website Việt Nam bị deface trên mirror-h.org

. Trong bài viết này, mình sẽ cùng mọi người khám phá một package thu thập dữ liệu có tên là goquery của golang. Mục tiêu chính của chương trình crawler này sẽ là lấy thông tin các website Việt Nam bị deface (là tấn công, phá hoại website, làm thay đổi giao diện hiển thị của một trang web, khi người

0 0 237

- vừa được xem lúc

Tạo ứng dụng craw dữ liệu bing với Golang, Mysql driver

Chào mọi người . Lâu lâu ta lại gặp nhau 1 lần, để tiếp tục series chia sẻ kiến thức về tech, hôm nay mình sẽ tìm hiểu và chia sẻ về 1 ngôn ngữ đang khá hot trong cộng đồng IT đó là Golang.

0 0 75

- vừa được xem lúc

Golang: Rest api and routing using MUX

Routing with MUX. Let's create a simple CRUD api for a blog site. # All . GET articles/ .

0 0 54