首页 > 其他分享 >[设计模式]行为型模式-观察者模式

[设计模式]行为型模式-观察者模式

时间:2024-05-31 23:54:31浏览次数:25  
标签:severity observer notified self 观察者 模式 myapp 设计模式

前言

观察者模式(Observer Pattern)是一种行为型设计模式,它定义了一种一对多的依赖关系,当一个对象的状态发生改变时,其所有依赖者都会收到通知并自动更新。

在观察者模式中,有两种主要的角色:

  • 观察者(Observer):观察者是一个接口或抽象类,它定义了一个更新的接口,使得被观察者在状态发生变化时可以通知观察者进行更新操作。
  • 被观察者(Subject):被观察者是一个类,它维护了一组观察者对象,并提供了添加、删除和通知观察者的方法。当被观察者的状态发生变化时,它会通知所有的观察者进行更新操作。

被观察者对象在状态或内容(数据)发生变化时,会通知所有观察者对象,使它们能够做出相应的变化(如自动更新自己的信息)。

工作原理

  1. 观察者通过订阅被观察者,注册自己到被观察者的观察者列表中。
  2. 被观察者维护了一个观察者列表,当自身状态发生变化时,遍历观察者列表,调用每个观察者的更新方法。
  3. 观察者收到通知后,执行相应的更新操作,通常是从被观察者获取最新的状态信息,并进行相应的处理。

优点

  1. 解耦性: 观察者模式将观察者和被观察者解耦,使得它们可以独立地变化和复用。
  2. 可扩展性: 可以根据需要动态地增加和删除观察者,从而实现系统的灵活性和可扩展性。
  3. 通知机制: 观察者模式提供了一种简单的通知机制,使得被观察者可以在状态发生变化时通知所有的观察者。

缺点

  1. 可能引起循环依赖: 如果观察者和被观察者之间存在双向依赖关系,可能会导致循环依赖的问题。这样会使系统变得复杂,难以维护和理解。
  2. 通知顺序不确定: 观察者模式中观察者的通知顺序通常是不确定的,这可能会导致一些问题,特别是在多个观察者对同一事件进行响应时。
  3. 可能导致性能问题: 如果被观察者对象频繁地改变状态,会导致大量的通知操作,可能会影响系统的性能。
  4. 可能引发并发问题: 如果在多线程环境下使用观察者模式,可能会引发并发问题,需要额外的同步措施来保证线程安全。
  5. 过多的细粒度对象: 观察者模式可能会导致系统中存在大量的细粒度的观察者对象,这可能会增加系统的复杂性和内存消耗。

示例代码

Go

代码文件: observer/observer.go

package observer

import "fmt"

// 观察者接口
type Observer interface {
	Update(myapp MyAPP)
}

// 被观察者
type MyAPP struct {
	observers []Observer
	serverity int
}

func (m *MyAPP) GetServerity() int {
	return m.serverity
}

func (m *MyAPP) SetServerity(s int) {
	if s < 0 || s > 3 {
		fmt.Println("serverity must be an integer between 0 and 3")
		return
	}
	m.serverity = s
	fmt.Printf("Current severity is %d.\n", m.serverity)
	m.notify()
}

func (m *MyAPP) notify() {
	for _, observer := range m.observers {
		observer.Update(*m)
	}
}

func (m *MyAPP) AddObserver(observer Observer) {
	m.observers = append(m.observers, observer)
}

type Employee struct{}

func (e *Employee) Update(myapp MyAPP) {
	if myapp.GetServerity() == 1 {
		fmt.Println("Employee: I'm notified!")
	}
}

type Manager struct{}

func (m *Manager) Update(myapp MyAPP) {
	if myapp.GetServerity() == 2 {
		fmt.Println("Manager: I'm notified!")
	}
}

type Director struct{}

func (d *Director) Update(myapp MyAPP) {
	if myapp.GetServerity() == 3 {
		fmt.Println("Director: I'm notified!")
	}
}

代码文件: main.go

package main

import (
	"design-pattern-go/observer"
)

func main() {
	myapp := &observer.MyAPP{}

	employee := &observer.Employee{}
	manager := &observer.Manager{}
	director := &observer.Director{}

	myapp.AddObserver(employee)
	myapp.AddObserver(manager)
	myapp.AddObserver(director)

	myapp.SetServerity(0)
	myapp.SetServerity(1)
	myapp.SetServerity(2)
	myapp.SetServerity(3)
	myapp.SetServerity(4)
}

运行结果

$ go run main.go

Current severity is 0.
Current severity is 1.
Employee: I'm notified!
Current severity is 2.
Manager: I'm notified!
Current severity is 3.
Director: I'm notified!
serverity must be an integer between 0 and 3

Python

from abc import ABCMeta, abstractmethod


class MyApp:
    """被观察者"""
    def __init__(self):
        self.__observers = []
        self.__severity = 0

    def get_severity(self):
        return self.__severity

    def set_severity(self, severity: int):
        if not isinstance(severity, int) or severity < 0 or severity > 3:
            raise ValueError("severity must be an integer between 0 and 3")
        self.__severity = severity
        print(f"current severity: {severity}")
        self.notify()

    def add_observer(self, observer):
        self.__observers.append(observer)
    
    def notify(self):
        """遍历观察者列表, 调用每个观察者的update方法"""
        for o in self.__observers:
            o.update(self)

class Observer(metaclass=ABCMeta):
    """观察者基类"""
    @abstractmethod
    def update(self, myapp: MyApp):
        pass


class Employee(Observer):
    def update(self, myapp: MyApp):
        if myapp.get_severity() == 1:
            print("An employee is notified")


class Manager(Observer):
    def update(self, myapp: MyApp):
        if myapp.get_severity() == 2:
            print("A manager is notified")

class Director(Observer):
    def update(self, myapp: MyApp):
        if myapp.get_severity() == 3:
            print("A director is notified")


if __name__ == "__main__":
    myapp = MyApp()

    employee = Employee()
    manager = Manager()
    director = Director()

    myapp.add_observer(employee)
    myapp.add_observer(manager)
    myapp.add_observer(director)

    myapp.set_severity(1)
    myapp.set_severity(2)
    myapp.set_severity(3)

运行结果:

$ python .\observer.py

current severity: 1
An employee is notified
current severity: 2
A manager is notified
current severity: 3
A director is notified

标签:severity,observer,notified,self,观察者,模式,myapp,设计模式
From: https://www.cnblogs.com/XY-Heruo/p/18225460

相关文章

  • 29-ESP32-S3-WIFI篇-00 STA模式扫描全部 AP
    ESP32-S3WIFI_Driver引言ESP32-S3是一款集成了Wi-Fi和蓝牙功能的芯片。关于WIFI的部分,其实内容比我想象的要多得多。所以通常来说,如果你想要编写自己的Wi-Fi应用程序,最快捷的方法就是先找一个类似的示例应用,然后将它的相关部分搬移到你的项目中,强烈建议在开始项目前先阅......
  • JS设计模式学习【待吸收】
    版权:千锋HTML5大前端教研院,源自大前端私房菜JS设计模式一.设计模式介绍设计模式是我们在解决问题的时候针对特定问题给出的简洁而优化的处理方案在JS设计模式中,最核心的思想:封装变化。将变与不变分离,确保变化的部分灵活、不变的部分稳定。二.构造器模式类似......
  • 闲鱼系列课 店群无货源模式-爆品打造硬件+软件+人工
    1-1闲鱼怎么设置2-2闲鱼正确养号3-3闲鱼店铺怎么布局4-4多账号怎么注册5-5怎么隐藏自己的店铺6-6会引流的宝贝视频操作7-7标题怎么写8-8日出30单的权重9-9客服系统-自动回复10-10闲鱼怎么测款11-11最有效的爆品打造方法12-12怎么解决闲鱼限流问题13-13怎么高效转......
  • 说说你对单例模式的理解?如何实现?
     一、是什么单例模式(SingletonPattern):创建型模式,提供了一种创建对象的最佳方式,这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建在应用程序运行期间,单例模式只会在全局作用域下创建一次实例对象,让所有需要调用的地方都共享这一单例对象,如下图所......
  • sqlSugar 使用原生模式链接数据库
    usingSystem.Reflection;usingzhulongxu_webapi_pro.Tools;namespacezhulongxu_webapi_pro.Services{///<summary>///初始化数据库///</summary>publicstaticclassInitDataBaseService{publicstaticvoidInitDataBase......
  • c/c++设计模式--组合模式
      namespace_nmsp1{//文件相关类classFile{public://构造函数File(stringname):m_sname(name){}//显示文件名voidShowName(stringlvlstr)//lvlstr:为了显示层次关系的缩进字符串内容{......
  • 23种设计模式之装饰模式
    装饰模式1、定义装饰模式:动态的给一个对象增加一些额外的职责。就扩展功能而言,装饰模式提供了一种比使用子类更加灵活的替代方案。2、装饰模式结构Component(抽象构建):它是具体构建和抽象装饰类的共同父类,声明了在具体构件中实现的业务方法。ConcreteComponent(具体构建):定......
  • 深入解析C#中的模式匹配:简洁高效的功能探索
    模式匹配是编程领域中一种强大的工具,用于检测表达式是否符合特定条件,C#通过一系列丰富且灵活的模式表达式与语句,极大地简化了这一过程。本文将逐一剖析C#提供的模式匹配特性,揭示其背后的简洁逻辑与强大功能。C#模式匹配核心组件C#模式匹配围绕两个基本构建块展开:表达式/语句和......
  • 设计模式:全网最全(23+10种)、最易懂(对比代码)、最简洁(三言两语)、最深度(带点评)的
    前言设计模式是软件开发中的重要工具,灵活掌握大量的设计模式,能够帮助我们编写更灵活、可维护和可扩展的代码。网上有许多关于设计模式的文章,往往把设计模式介绍得高深莫测,墨守成规。于是,不久前萌发了写一篇简单易懂的设计模式介绍的文章的想法。在开始之前,我想强调切勿滥......
  • 设计模式——单例模式
    一。引言当我们写一个体量比较大的代码使,如果这是堆积罗列,那么会发现有许多冗余的情况,并且还不利于团队共同协作,代码难以定位。于是为了解决这些问题,提高代码的可读性,减少耦合度,我们引入了设计模式。设计模式就像盖房子时的图纸,根据这些图纸的指导可以让我们把房子建的更漂......