Go和Java实现观察者模式

这篇具有很好参考价值的文章主要介绍了Go和Java实现观察者模式。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Go和Java实现观察者模式

在监控系统中,我们需要采集监控指标的信息,假设当采集的指标信息超过阈值时我们需要对该监控指标持久化到

数据库中并且进行告警。

本文通过指标采集持久化和告警来说明观察者模式的使用,使用Go语言和Java语言实现。

1、观察者模式

观察者模式是一种行为型设计模式,它定义了一种一对多的依赖关系,当一个对象的状态发生改变时,其所有依赖

者都会收到通知并自动更新。

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

者模式属于行为型模式。

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

  • 并被自动更新。

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

  • 何时使用:一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播

    通知。

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

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

  • 应用实例:1、拍卖的时候,拍卖师观察最高标价,然后通知给其他竞价者竞价。 2、西游记里面悟空请求菩

    萨降服红孩儿,菩萨洒了一地水招来一个老乌龟,这个乌龟就是观察者,他观察菩萨洒水这个动作。

  • 优点:1、观察者和被观察者是抽象耦合的。 2、建立一套触发机制。

  • 缺点:1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时

    间。 2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系

    统崩溃。 3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道

    观察目标发生了变化。

  • 使用场景:

    一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自

    独立地改变和复用。

    一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象

    之间的耦合度。

    一个对象必须通知其他对象,而并不知道这些对象是谁。

    需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者

    模式创建一种链式触发机制。

  • 注意事项:1、JAVA 中已经有了对观察者模式的支持类。 2、避免循环引用。 3、如果顺序执行,某一观察者

    错误会导致系统卡壳,一般采用异步方式。

  • 观察者模式包含以下几个核心角色:

    主题(Subject):也称为被观察者或可观察者,它是具有状态的对象,并维护着一个观察者列表。主题提供

    了添加、删除和通知观察者的方法。

    观察者(Observer):观察者是接收主题通知的对象。观察者需要实现一个更新方法,当收到主题的通知

    时,调用该方法进行更新操作。

    具体主题(Concrete Subject):具体主题是主题的具体实现类。它维护着观察者列表,并在状态发生改变时

    通知观察者。

    具体观察者(Concrete Observer):具体观察者是观察者的具体实现类。它实现了更新方法,定义了在收到

    主题通知时需要执行的具体操作。

观察者模式通过将主题和观察者解耦,实现了对象之间的松耦合。当主题的状态发生改变时,所有依赖于它的观察

者都会收到通知并进行相应的更新。

2、Go实现观察者模式

package observer

// ISubject通知者
type ISubject interface {
	Register(observer IObserver)
	Remove(observer IObserver)
	Notify(metric Metric)
}
package observer

// MetricSubject指标通知者
type MetricSubject struct {
	observers []IObserver
}

type Metric struct {
	Name  string
	Value float64
	Time  string
}

func (metricSubject *MetricSubject) Register(observer IObserver) {
	metricSubject.observers = append(metricSubject.observers, observer)
}

func (metricSubject *MetricSubject) Remove(observer IObserver) {
	for i, ob := range metricSubject.observers {
		if ob == observer {
			metricSubject.observers = append(metricSubject.observers[:i], metricSubject.observers[i+1:]...)
		}
	}
}

func (metricSubject *MetricSubject) Notify(metric Metric) {
	for _, o := range metricSubject.observers {
		o.Update(metric)
	}
}
package observer

// IObserver观察者
type IObserver interface {
	Update(metric Metric)
}
package observer

import "fmt"

// alert观察者
type AlertObserver struct {
}

func (alertObserver * AlertObserver) Update(metric Metric){
   fmt.Printf("[%s] 指标 [%s] 的值为 [%.1f] 超过阈值,进行告警!\n", metric.Time, metric.Name, metric.Value)
}
package observer

import "fmt"

// db观察者
type DbObserver struct {
}

func (dbObserver *DbObserver) Update(metric Metric) {
	fmt.Printf("[%s] 指标 [%s] 的值为 [%.1f] 超过阈值,保存到数据库!\n", metric.Time, metric.Name, metric.Value)
}
package main

import (
	"fmt"
	. "proj/observer"
	"time"
)

func main() {
	sub := &MetricSubject{}
	alert := &AlertObserver{}
	db := &DbObserver{}
	sub.Register(alert)
	sub.Register(db)
	sub.Notify(Metric{Name: "CPU", Value: 90, Time: time.Now().Format("2006-01-02 15:04:05")})
	sub.Notify(Metric{Name: "Memory", Value: 80, Time: time.Now().Format("2006-01-02 15:04:05")})
	fmt.Println("==========")
	// 后面不需要进行持久化了
	sub.Remove(db)
	sub.Notify(Metric{Name: "CPU", Value: 90, Time: time.Now().Format("2006-01-02 15:04:05")})
	sub.Notify(Metric{Name: "Memory", Value: 80, Time: time.Now().Format("2006-01-02 15:04:05")})
}
# 程序输出
[2023-07-11 22:05:34] 指标 [CPU] 的值为 [90.0] 超过阈值,进行告警!
[2023-07-11 22:05:34] 指标 [CPU] 的值为 [90.0] 超过阈值,保存到数据库!
[2023-07-11 22:05:34] 指标 [Memory] 的值为 [80.0] 超过阈值,进行告警!
[2023-07-11 22:05:34] 指标 [Memory] 的值为 [80.0] 超过阈值,保存到数据库!
==========
[2023-07-11 22:05:34] 指标 [CPU] 的值为 [90.0] 超过阈值,进行告警!
[2023-07-11 22:05:34] 指标 [Memory] 的值为 [80.0] 超过阈值,进行告警!

3、Java实现观察者模式

package com.observer;

import java.util.List;

// ISubject通知者
public abstract class ISubject {

    List<IObserver> observerList;

    abstract void Register(IObserver observer);

    abstract void Remove(IObserver observer);

    abstract void Notify(Metric metric);
}
package com.observer;

import java.util.ArrayList;

// MetricSubject指标通知者
public class MetricSubject extends ISubject {

    public MetricSubject() {
        this.observerList = new ArrayList<>();
    }

    @Override
    void Register(IObserver observer) {
        observerList.add(observer);
    }

    @Override
    void Remove(IObserver observer) {
        observerList.remove(observer);
    }

    @Override
    void Notify(Metric metric) {
        for (IObserver observer : observerList) {
            observer.Update(metric);
        }
    }
}
package com.observer;

// IObserver观察者
public interface IObserver {

    void Update(Metric metric);
}
package com.observer;

// db观察者
public class DbObserver implements IObserver {

    @Override
    public void Update(Metric metric) {
        String url = "[%s] 指标 [%s] 的值为 [%.1f] 超过阈值,保存到数据库!";
        System.out.println(String.format(url, metric.Time, metric.Name, metric.Value));
    }
}
package com.observer;

// alert观察者
public class AlertObserver implements IObserver {

    @Override
    public void Update(Metric metric) {
        String url = "[%s] 指标 [%s] 的值为 [%.1f] 超过阈值,进行告警!";
        System.out.println(String.format(url, metric.Time, metric.Name, metric.Value));
    }
}
package com.observer;

import java.text.SimpleDateFormat;
import java.util.Date;

public class Test {
    public static void main(String[] args) {
        ISubject subject = new MetricSubject();
        IObserver observer1 = new DbObserver();
        IObserver observer2 = new AlertObserver();
        subject.Register(observer1);
        subject.Register(observer2);
        subject.Notify(new Metric("CPU", 90, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())));
        subject.Notify(new Metric("Memory", 80, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())));
        System.out.println("==========");
        // 后面不需要进行持久化了
        subject.Remove(observer1);
        subject.Notify(new Metric("CPU", 90, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())));
        subject.Notify(new Metric("Memory", 80, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())));
    }
}
# 程序输出
[2023-07-12 20:42:04] 指标 [CPU] 的值为 [90.0] 超过阈值,保存到数据库!
[2023-07-12 20:42:04] 指标 [CPU] 的值为 [90.0] 超过阈值,进行告警!
[2023-07-12 20:42:04] 指标 [Memory] 的值为 [80.0] 超过阈值,保存到数据库!
[2023-07-12 20:42:04] 指标 [Memory] 的值为 [80.0] 超过阈值,进行告警!
==========
[2023-07-12 20:42:04] 指标 [CPU] 的值为 [90.0] 超过阈值,进行告警!
[2023-07-12 20:42:04] 指标 [Memory] 的值为 [80.0] 超过阈值,进行告警!

4、使用Go实现EventBus

我们实现一个支持以下功能的事件总线:

1、异步不阻塞

2、支持任意参数值文章来源地址https://www.toymoban.com/news/detail-594585.html

package eventbus

import (
	"fmt"
	"reflect"
	"sync"
)

// Bus
type Bus interface {
	Subscribe(topic string, handler interface{}) error
	Publish(topic string, args ...interface{})
}

// AsyncEventBus异步事件总线
type AsyncEventBus struct {
	handlers map[string][]reflect.Value
	lock     sync.Mutex
}

// NewAsyncEventBus
func NewAsyncEventBus() *AsyncEventBus {
	return &AsyncEventBus{
		handlers: map[string][]reflect.Value{},
		lock:     sync.Mutex{},
	}
}

// Subscribe订阅
func (bus *AsyncEventBus) Subscribe(topic string, f interface{}) error {
	bus.lock.Lock()
	defer bus.lock.Unlock()
	v := reflect.ValueOf(f)
	if v.Type().Kind() != reflect.Func {
		return fmt.Errorf("handler is not a function")
	}
	handler, ok := bus.handlers[topic]
	if !ok {
		handler = []reflect.Value{}
	}
	handler = append(handler, v)
	bus.handlers[topic] = handler
	return nil
}

// Publish发布
// 这里异步执行,并且不会等待返回结果
func (bus *AsyncEventBus) Publish(topic string, args ...interface{}) {
	handlers, ok := bus.handlers[topic]
	if !ok {
		fmt.Println("not found handlers in topic:", topic)
		return
	}
	params := make([]reflect.Value, len(args))
	for i, arg := range args {
		params[i] = reflect.ValueOf(arg)
	}
	for i := range handlers {
		go handlers[i].Call(params)
	}
}
package main

import (
	"fmt"
	. "proj/eventbus"
	"time"
)

func sub1(msg1, msg2 string) {
	time.Sleep(1 * time.Microsecond)
	fmt.Printf("sub1, %s %s\n", msg1, msg2)
}

func sub2(msg1, msg2 string) {
	fmt.Printf("sub2, %s %s\n", msg1, msg2)
}

func main() {
	bus := NewAsyncEventBus()
	bus.Subscribe("topic1", sub1)
	bus.Subscribe("topic1", sub2)
	bus.Publish("topic1", "1", "2")
	bus.Publish("topic1", "a", "b")
	time.Sleep(1 * time.Second)
}
# 程序输出
sub2, a b
sub2, 1 2
sub1, 1 2
sub1, a b

到了这里,关于Go和Java实现观察者模式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【设计模式——学习笔记】23种设计模式——观察者模式Observer(原理讲解+应用场景介绍+案例介绍+Java代码实现)

    有一个天气预报项目,需求如下: 气象站可以将每天测量到的温度、湿度、气压等等以公告的形式发布出去(比如发布到自己的网站或第三方) 需要设计开放型API,便于其他第三方也能接入气象站获取数据 提供温度、气压、湿度的接口 测量数据更新时,要能实时的通知给第三

    2024年02月14日
    浏览(38)
  • java设计模式(二十)观察者模式

    观察者模式 又叫发布订阅模式(Publish/Subscribe),它定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生变化时就会通知所有的观察者对象,使得它们能够自动更新自己。 1.抽象目标类(Subject) :它用一个列表记录当前目标对象

    2024年02月08日
    浏览(43)
  • Java观察者设计模式

    观察者模式,定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。在Java中,观察者模式通常由两个接口组成:Subject和Observer。Subject是被观察的对象,Observer是观察者。Subject接口定义了一系列方法,用于添加、删

    2024年02月16日
    浏览(36)
  • java设计模式学习之【观察者模式】

    想象你在一个在线拍卖会上竞标一件珍贵的艺术品。每当有人出价更高,系统都会立即通知你。这个实时更新机制使你可以做出快速反应。这种模式,在软件开发中称为观察者模式,是一种广泛应用于实现事件驱动系统的设计模式。 观察者模式(Observer Pattern)是一种行为型

    2024年02月03日
    浏览(40)
  • java设计模式-观察者模式(jdk内置)

    上一篇我们学习了 观察者模式。 观察者和被观察者接口都是我们自己定义的,整个设计模式我们从无到有都是自己设计的,其实,java已经内置了这个设计模式,我们只需要定义实现类即可。 下面我们不多说明,直接示例代码,例子依然同 观察者模式篇章,建议先去看看。

    2024年02月15日
    浏览(36)
  • Java设计模式系列--观察者模式写法2:JDK

    原文网址:Java设计模式系列--观察者模式写法2:JDK_IT利刃出鞘的博客-CSDN博客 说明 本文用示例介绍观察者模式的一种写法:JDK。 JDK的观察者模式简介 在 Java 中,java.util.Observable 类和 java.util.Observer 接口定义了观察者模式,只要实现这两个接口就可以编写观察者模式。 1. Ob

    2024年02月13日
    浏览(39)
  • 【设计模式】Head First 设计模式——观察者模式 C++实现

    设计模式最大的作用就是在变化和稳定中间寻找隔离点,然后分离它们,从而管理变化。将变化像小兔子一样关到笼子里,让它在笼子里随便跳,而不至于跳出来把你整个房间给污染掉。 主题对象(出版者)管理某些数据,当主题内的数据改变,就会通知观察者(订阅者)。

    2024年02月10日
    浏览(41)
  • 「观察者(Observer)」设计模式 Swift实现

    观察者设计模式(Observer Pattern)是一种行为型设计模式,它定义了对象之间的一种一对多的依赖关系,使得当一个对象的状态发生变化时,所有依赖于它的对象都会受到通知并自动更新。 在这种模式中,被观察者对象(Subject)存储其观察者对象(Observer)列表,并提供了用

    2024年02月16日
    浏览(39)
  • Go和Java实现观察者模式

    在监控系统中,我们需要采集监控指标的信息,假设当采集的指标信息超过阈值时我们需要对该监控指标持久化到 数据库中并且进行告警。 本文通过指标采集持久化和告警来说明观察者模式的使用,使用Go语言和Java语言实现。 观察者模式是一种行为型设计模式,它定义了一

    2024年02月16日
    浏览(35)
  • 【设计模式】观察者模式

    观察者模式(又被称为发布-订阅(Publish/Subscribe)模式,属于行为型模式的一种,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。 Subject:抽象主题(被观察者

    2024年02月13日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包