23种设计模式-观察者模式
回头看最近的代码,发现不再难以下咽,不自觉间使用的一些设计模式颇值得拿出来回味。过年期间做了一些设计模式方面的总结学习,会陆续拿出来与大家分享。如果觉得不错的,记得赞赏、关注、转发三连。
1. 模式的定义与特点
观察者(Observer)模式的定义:指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式,它是对象行为型模式。
2. 模式的结构和实现
实现观察者模式时要注意具体目标对象和具体观察者对象之间不能直接调用,否则将使两者之间紧密耦合起来,这违反了面向对象的设计原则。
1)主要角色
-
抽象主题 Subject:也叫 抽象目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。
-
具体主题 Concrete Subject:也叫 具体目标类,它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。
-
抽象观察者 Observer:它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。
-
具体观察者 Concrete Observer:实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。
2)主要结构
3. 代码实现
1)go语言版本
场景:微信公众号与微信用户
// subject.go
package main
type Subject interface {
Add(ob Observer)
Remove(ob Observer)
Notify()
}
type ProgramSubject struct {
observers map[Observer]int64
}
func (sub *ProgramSubject) Add(ob Observer) {
if sub.observers == nil {
sub.observers = make(map[Observer]int64)
}
sub.observers[ob] = 1
}
func (sub *ProgramSubject) Remove(ob Observer) {
delete(sub.observers, ob)
}
func (sub *ProgramSubject) Notify() {
for ob, _ := range sub.observers{
ob.Receive()
}
}
// observer.go
package main
import "fmt"
type Observer interface {
Receive()
}
type UserObserver struct {
Name string
}
func (ob UserObserver)Receive() {
fmt.Println("user received:", ob.Name)
}
// main.go
package main
import "fmt"
func main() {
var user1 Observer = UserObserver{Name: "alice"}
var user2 Observer = UserObserver{Name: "bob"}
var program Subject = &ProgramSubject{}
program.Add(user1)
program.Add(user2)
program.Notify()
fmt.Println("=======")
program.Remove(user1)
program.Notify()
}
运行结果
user received: alice
user received: bob
=======
user received: bob
4. 模式应用场景
在软件系统中,当系统一方行为依赖另一方行为的变动时,可使用观察者模式松耦合联动双方,使得一方的变动可以通知到感兴趣的另一方对象,从而让另一方对象对此做出响应。
常见适用情形:
1)对象间存在一对多关系,一个对象的状态发生改变会影响其他对象。
2)当一个抽象模型有两个方面,其中一个方面依赖于另一方面时,可将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。
3)实现类似广播机制的功能,不需要知道具体收听者,只需分发广播,系统中感兴趣的对象会自动接收该广播。
4)多层级嵌套使用,形成一种链式触发机制,使得事件具备跨域(跨越两种观察者类型)通知。