观察者设计模式

当对象间存在一对多关系时,则使用观察者模式。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。

介绍

意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。

主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。

何时使用:一个对象的状态发生改变,所有的依赖对象都将得到通知,进行广播通知。

如何解决:使用面向对象的技术,可以将这种依赖关系弱化。

关键代码:在抽象类里有一个slice存在观察者们。

优点:

  • 观察者和被观察者是抽象耦合关系
  • 建立一套触发机制。

缺点:

  • 如果一个被观察者对象有很多的直接就和间接的观察者的话,将所有的观察者都通知到会话费很多时间
  • 如果在观察者喝酒观察目标之间有循环依赖的话,观察目标会触发他们之间进行循环调用,可能会导致系统崩溃。
  • 观察者模式没有相应的机制让观察者直到所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化

使用场景:

  • 一个抽象模式有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使他们可以各自独立改变和复用
  • 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
  • 一个对象必须通知其他对象,而并不知道这些对象是谁。
  • 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象,可以使用观察者模式创建一种链式触发机制。

实现

观察者模式使用三个类Subject、Observer和Client。Subject对象带有绑定观察者到Client对象和从Client对象解绑观察者的方法。我们创建Subject类、Observer抽象和扩展了抽象类Observer的实体类。

ObserverPatternDemo,我们的演示类使用 Subject 和实体类对象来演示观察者模式。

Golang观察者设计模式(十九) _ JavaClub全栈架构师技术笔记

代码:

package ObserverPattern

type Subject struct {
	observers []Observer
	state     int
}

func (s *Subject) GetState() int {
	return s.state
}

func (s *Subject) SetState(state int) {
	s.state = state
	s.NotifyAllObservers()
}

func (s *Subject) Attach(observer Observer) {
	s.observers = append(s.observers, observer)
}

func (s *Subject) NotifyAllObservers() {
	for _, observer := range s.observers {
		observer.Update()
	}
}

 

package ObserverPattern

import (
	"fmt"
)

type Observer interface {
	Update()
}

type BinaryObserver struct {
	subject *Subject
}

func (b *BinaryObserver) BinaryObserver(subject *Subject) {
	b.subject = subject
	b.subject.Attach(b)
}

func (b *BinaryObserver) Update() {
	fmt.Println("Binary String: ", b.subject.GetState())
}

type OctalObserver struct {
	subject *Subject
}

func (o *OctalObserver) OctalObserver(subject *Subject) {
	o.subject = subject
	o.subject.Attach(o)
}

func (o *OctalObserver) Update() {
	fmt.Println("Octal String:", o.subject.GetState())
}

type HexaObserver struct {
	subject *Subject
}

func (h *HexaObserver) HexaObserver(subject *Subject) {
	h.subject = subject
	h.subject.Attach(h)
}

func (h *HexaObserver) Update() {
	fmt.Println("Hex String:", h.subject.GetState())
}

测试:

func testObserverPattern() {
	subject := new(ObserverPattern.Subject)
	new(ObserverPattern.HexaObserver).HexaObserver(subject)
	new(ObserverPattern.OctalObserver).OctalObserver(subject)
	new(ObserverPattern.BinaryObserver).BinaryObserver(subject)
	fmt.Println("First state change:15")
	subject.SetState(15)
	fmt.Println("Second state change:10")
	subject.SetState(10)
}

输出

First state change:15
Hex String: 15
Octal String: 15
Binary String:  15
Second state change:10
Hex String: 10
Octal String: 10
Binary String:  10