봄맞이 세일
옵서버

Go로 작성된 옵서버

옵서버 패턴은 일부 객체들이 다른 객체들에 자신의 상태 변경에 대해 알릴 수 있는 행동 디자인 패턴입니다.

옵서버 패턴은 구독자 인터페이스를 구현하는 모든 객체에 대한 이러한 이벤트들을 구독 및 구독 취소하는 방법을 제공합니다.

개념적인 예시

예시의 전자 상거래 사이트에서는 제품들이 때때로 품절됩니다. 품절된 특정 상품에 관심이 있는 고객들이 있을 수 있으며, 이 문제에 대한 세 가지 해결책이 존재합니다:

  1. 고객은 제품의 재고 여부를 일정 빈도로 계속 확인합니다.
  2. 전자 상거래 사이트는 재고가 있는 사용 가능한 모든 새 항목에 대한 알림을 고객에게 지나치게 자주 제공합니다.
  3. 고객은 자신이 관심이 있는 제품의 재고 여부에 대해만 구독을 하고 해당 제품이 들어왔을 때만 알림을 받습니다. 또 여러 손님은 같은 제품의 재고 여부에 구독을 할 수 있습니다.

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

다른 언어로 작성된 옵서버

C#으로 작성된 옵서버 C++로 작성된 옵서버 자바로 작성된 옵서버 PHP로 작성된 옵서버 파이썬으로 작성된 옵서버 루비로 작성된 옵서버 러스트로 작성된 옵서버 스위프트로 작성된 옵서버 타입스크립트로 작성된 옵서버