![옵서버](/images/patterns/cards/observer-mini.png?id=fd2081ab1cff29c60b499bcf6a62786a)
Go로 작성된 옵서버
옵서버 패턴은 일부 객체들이 다른 객체들에 자신의 상태 변경에 대해 알릴 수 있는 행동 디자인 패턴입니다.
옵서버 패턴은 구독자 인터페이스를 구현하는 모든 객체에 대한 이러한 이벤트들을 구독 및 구독 취소하는 방법을 제공합니다.
개념적인 예시
예시의 전자 상거래 사이트에서는 제품들이 때때로 품절됩니다. 품절된 특정 상품에 관심이 있는 고객들이 있을 수 있으며, 이 문제에 대한 세 가지 해결책이 존재합니다:
- 고객은 제품의 재고 여부를 일정 빈도로 계속 확인합니다.
- 전자 상거래 사이트는 재고가 있는 사용 가능한 모든 새 항목에 대한 알림을 고객에게 지나치게 자주 제공합니다.
- 고객은 자신이 관심이 있는 제품의 재고 여부에 대해만 구독을 하고 해당 제품이 들어왔을 때만 알림을 받습니다. 또 여러 손님은 같은 제품의 재고 여부에 구독을 할 수 있습니다.
3번째 옵션이 가장 효과적인 것 같습니다. 옵서버 패턴은 해당 옵션을 가능하게 하며 패턴의 주 컴포넌트들은 다음과 같습니다:
- 주제: 어떤 일이 발생했을 때 이벤트를 게시하는 인스턴스입니다.
- 옵서버: 주제 이벤트들을 구독하고 이벤트 발생 시 알림을 받습니다.
subject.go: 주제
package main
type Subject interface {
register(observer Observer)
deregister(observer Observer)
notifyAll()
}
item.go: 구상 주제
package main
import "fmt"
type Item struct {
observerList []Observer
name string
inStock bool
}
func newItem(name string) *Item {
return &Item{
name: name,
}
}
func (i *Item) updateAvailability() {
fmt.Printf("Item %s is now in stock\n", i.name)
i.inStock = true
i.notifyAll()
}
func (i *Item) register(o Observer) {
i.observerList = append(i.observerList, o)
}
func (i *Item) deregister(o Observer) {
i.observerList = removeFromslice(i.observerList, o)
}
func (i *Item) notifyAll() {
for _, observer := range i.observerList {
observer.update(i.name)
}
}
func removeFromslice(observerList []Observer, observerToRemove Observer) []Observer {
observerListLength := len(observerList)
for i, observer := range observerList {
if observerToRemove.getID() == observer.getID() {
observerList[observerListLength-1], observerList[i] = observerList[i], observerList[observerListLength-1]
return observerList[:observerListLength-1]
}
}
return observerList
}
observer.go: 옵서버
package main
type Observer interface {
update(string)
getID() string
}
customer.go: 구상 옵서버
package main
import "fmt"
type Customer struct {
id string
}
func (c *Customer) update(itemName string) {
fmt.Printf("Sending email to customer %s for item %s\n", c.id, itemName)
}
func (c *Customer) getID() string {
return c.id
}
main.go: 클라이언트 코드
package main
func main() {
shirtItem := newItem("Nike Shirt")
observerFirst := &Customer{id: "abc@gmail.com"}
observerSecond := &Customer{id: "xyz@gmail.com"}
shirtItem.register(observerFirst)
shirtItem.register(observerSecond)
shirtItem.updateAvailability()
}
output.txt: 실행 결과
Item Nike Shirt is now in stock
Sending email to customer abc@gmail.com for item Nike Shirt
Sending email to customer xyz@gmail.com for item Nike Shirt