国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Go和Java實(shí)現(xiàn)觀察者模式

這篇具有很好參考價(jià)值的文章主要介紹了Go和Java實(shí)現(xiàn)觀察者模式。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

Go和Java實(shí)現(xiàn)觀察者模式

在監(jiān)控系統(tǒng)中,我們需要采集監(jiān)控指標(biāo)的信息,假設(shè)當(dāng)采集的指標(biāo)信息超過閾值時(shí)我們需要對該監(jiān)控指標(biāo)持久化到

數(shù)據(jù)庫中并且進(jìn)行告警。

本文通過指標(biāo)采集持久化和告警來說明觀察者模式的使用,使用Go語言和Java語言實(shí)現(xiàn)。

1、觀察者模式

觀察者模式是一種行為型設(shè)計(jì)模式,它定義了一種一對多的依賴關(guān)系,當(dāng)一個(gè)對象的狀態(tài)發(fā)生改變時(shí),其所有依賴

者都會收到通知并自動更新。

當(dāng)對象間存在一對多關(guān)系時(shí),則使用觀察者模式。比如,當(dāng)一個(gè)對象被修改時(shí),則會自動通知依賴它的對象。觀察

者模式屬于行為型模式。

  • 意圖:定義對象間的一種一對多的依賴關(guān)系,當(dāng)一個(gè)對象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對象都得到通知

  • 并被自動更新。

  • 主要解決:一個(gè)對象狀態(tài)改變給其他對象通知的問題,而且要考慮到易用和低耦合,保證高度的協(xié)作。

  • 何時(shí)使用:一個(gè)對象(目標(biāo)對象)的狀態(tài)發(fā)生改變,所有的依賴對象(觀察者對象)都將得到通知,進(jìn)行廣播

    通知。

  • 如何解決:使用面向?qū)ο蠹夹g(shù),可以將這種依賴關(guān)系弱化。

  • 關(guān)鍵代碼:在抽象類里有一個(gè) ArrayList 存放觀察者們。

  • 應(yīng)用實(shí)例:1、拍賣的時(shí)候,拍賣師觀察最高標(biāo)價(jià),然后通知給其他競價(jià)者競價(jià)。 2、西游記里面悟空請求菩

    薩降服紅孩兒,菩薩灑了一地水招來一個(gè)老烏龜,這個(gè)烏龜就是觀察者,他觀察菩薩灑水這個(gè)動作。

  • 優(yōu)點(diǎn):1、觀察者和被觀察者是抽象耦合的。 2、建立一套觸發(fā)機(jī)制。

  • 缺點(diǎn):1、如果一個(gè)被觀察者對象有很多的直接和間接的觀察者的話,將所有的觀察者都通知到會花費(fèi)很多時(shí)

    間。 2、如果在觀察者和觀察目標(biāo)之間有循環(huán)依賴的話,觀察目標(biāo)會觸發(fā)它們之間進(jìn)行循環(huán)調(diào)用,可能導(dǎo)致系

    統(tǒng)崩潰。 3、觀察者模式?jīng)]有相應(yīng)的機(jī)制讓觀察者知道所觀察的目標(biāo)對象是怎么發(fā)生變化的,而僅僅只是知道

    觀察目標(biāo)發(fā)生了變化。

  • 使用場景:

    一個(gè)抽象模型有兩個(gè)方面,其中一個(gè)方面依賴于另一個(gè)方面。將這些方面封裝在獨(dú)立的對象中使它們可以各自

    獨(dú)立地改變和復(fù)用。

    一個(gè)對象的改變將導(dǎo)致其他一個(gè)或多個(gè)對象也發(fā)生改變,而不知道具體有多少對象將發(fā)生改變,可以降低對象

    之間的耦合度。

    一個(gè)對象必須通知其他對象,而并不知道這些對象是誰。

    需要在系統(tǒng)中創(chuàng)建一個(gè)觸發(fā)鏈,A對象的行為將影響B(tài)對象,B對象的行為將影響C對象……,可以使用觀察者

    模式創(chuàng)建一種鏈?zhǔn)接|發(fā)機(jī)制。

  • 注意事項(xiàng):1、JAVA 中已經(jīng)有了對觀察者模式的支持類。 2、避免循環(huán)引用。 3、如果順序執(zhí)行,某一觀察者

    錯(cuò)誤會導(dǎo)致系統(tǒng)卡殼,一般采用異步方式。

  • 觀察者模式包含以下幾個(gè)核心角色:

    主題(Subject):也稱為被觀察者或可觀察者,它是具有狀態(tài)的對象,并維護(hù)著一個(gè)觀察者列表。主題提供

    了添加、刪除和通知觀察者的方法。

    觀察者(Observer):觀察者是接收主題通知的對象。觀察者需要實(shí)現(xiàn)一個(gè)更新方法,當(dāng)收到主題的通知

    時(shí),調(diào)用該方法進(jìn)行更新操作。

    具體主題(Concrete Subject):具體主題是主題的具體實(shí)現(xiàn)類。它維護(hù)著觀察者列表,并在狀態(tài)發(fā)生改變時(shí)

    通知觀察者。

    具體觀察者(Concrete Observer):具體觀察者是觀察者的具體實(shí)現(xiàn)類。它實(shí)現(xiàn)了更新方法,定義了在收到

    主題通知時(shí)需要執(zhí)行的具體操作。

觀察者模式通過將主題和觀察者解耦,實(shí)現(xiàn)了對象之間的松耦合。當(dāng)主題的狀態(tài)發(fā)生改變時(shí),所有依賴于它的觀察

者都會收到通知并進(jìn)行相應(yīng)的更新。

2、Go實(shí)現(xiàn)觀察者模式

package observer

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

// MetricSubject指標(biāo)通知者
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] 指標(biāo) [%s] 的值為 [%.1f] 超過閾值,進(jìn)行告警!\n", metric.Time, metric.Name, metric.Value)
}
package observer

import "fmt"

// db觀察者
type DbObserver struct {
}

func (dbObserver *DbObserver) Update(metric Metric) {
	fmt.Printf("[%s] 指標(biāo) [%s] 的值為 [%.1f] 超過閾值,保存到數(shù)據(jù)庫!\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("==========")
	// 后面不需要進(jìn)行持久化了
	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] 指標(biāo) [CPU] 的值為 [90.0] 超過閾值,進(jìn)行告警!
[2023-07-11 22:05:34] 指標(biāo) [CPU] 的值為 [90.0] 超過閾值,保存到數(shù)據(jù)庫!
[2023-07-11 22:05:34] 指標(biāo) [Memory] 的值為 [80.0] 超過閾值,進(jìn)行告警!
[2023-07-11 22:05:34] 指標(biāo) [Memory] 的值為 [80.0] 超過閾值,保存到數(shù)據(jù)庫!
==========
[2023-07-11 22:05:34] 指標(biāo) [CPU] 的值為 [90.0] 超過閾值,進(jìn)行告警!
[2023-07-11 22:05:34] 指標(biāo) [Memory] 的值為 [80.0] 超過閾值,進(jìn)行告警!

3、Java實(shí)現(xiàn)觀察者模式

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指標(biāo)通知者
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] 指標(biāo) [%s] 的值為 [%.1f] 超過閾值,保存到數(shù)據(jù)庫!";
        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] 指標(biāo) [%s] 的值為 [%.1f] 超過閾值,進(jìn)行告警!";
        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("==========");
        // 后面不需要進(jìn)行持久化了
        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] 指標(biāo) [CPU] 的值為 [90.0] 超過閾值,保存到數(shù)據(jù)庫!
[2023-07-12 20:42:04] 指標(biāo) [CPU] 的值為 [90.0] 超過閾值,進(jìn)行告警!
[2023-07-12 20:42:04] 指標(biāo) [Memory] 的值為 [80.0] 超過閾值,保存到數(shù)據(jù)庫!
[2023-07-12 20:42:04] 指標(biāo) [Memory] 的值為 [80.0] 超過閾值,進(jìn)行告警!
==========
[2023-07-12 20:42:04] 指標(biāo) [CPU] 的值為 [90.0] 超過閾值,進(jìn)行告警!
[2023-07-12 20:42:04] 指標(biāo) [Memory] 的值為 [80.0] 超過閾值,進(jìn)行告警!

4、使用Go實(shí)現(xiàn)EventBus

我們實(shí)現(xiàn)一個(gè)支持以下功能的事件總線:

1、異步不阻塞

2、支持任意參數(shù)值文章來源地址http://www.zghlxwxcb.cn/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發(fā)布
// 這里異步執(zhí)行,并且不會等待返回結(jié)果
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

到了這里,關(guān)于Go和Java實(shí)現(xiàn)觀察者模式的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【設(shè)計(jì)模式——學(xué)習(xí)筆記】23種設(shè)計(jì)模式——觀察者模式Observer(原理講解+應(yīng)用場景介紹+案例介紹+Java代碼實(shí)現(xiàn))

    【設(shè)計(jì)模式——學(xué)習(xí)筆記】23種設(shè)計(jì)模式——觀察者模式Observer(原理講解+應(yīng)用場景介紹+案例介紹+Java代碼實(shí)現(xiàn))

    有一個(gè)天氣預(yù)報(bào)項(xiàng)目,需求如下: 氣象站可以將每天測量到的溫度、濕度、氣壓等等以公告的形式發(fā)布出去(比如發(fā)布到自己的網(wǎng)站或第三方) 需要設(shè)計(jì)開放型API,便于其他第三方也能接入氣象站獲取數(shù)據(jù) 提供溫度、氣壓、濕度的接口 測量數(shù)據(jù)更新時(shí),要能實(shí)時(shí)的通知給第三

    2024年02月14日
    瀏覽(20)
  • java設(shè)計(jì)模式(二十)觀察者模式

    java設(shè)計(jì)模式(二十)觀察者模式

    觀察者模式 又叫發(fā)布訂閱模式(Publish/Subscribe),它定義了一種一對多的關(guān)系,讓多個(gè)觀察者對象同時(shí)監(jiān)聽某一個(gè)主題對象,這個(gè)主題對象的狀態(tài)發(fā)生變化時(shí)就會通知所有的觀察者對象,使得它們能夠自動更新自己。 1.抽象目標(biāo)類(Subject) :它用一個(gè)列表記錄當(dāng)前目標(biāo)對象

    2024年02月08日
    瀏覽(19)
  • Java觀察者設(shè)計(jì)模式

    觀察者模式,定義了對象之間的一對多依賴關(guān)系,當(dāng)一個(gè)對象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對象都得到通知并被自動更新。在Java中,觀察者模式通常由兩個(gè)接口組成:Subject和Observer。Subject是被觀察的對象,Observer是觀察者。Subject接口定義了一系列方法,用于添加、刪

    2024年02月16日
    瀏覽(28)
  • java設(shè)計(jì)模式學(xué)習(xí)之【觀察者模式】

    java設(shè)計(jì)模式學(xué)習(xí)之【觀察者模式】

    想象你在一個(gè)在線拍賣會上競標(biāo)一件珍貴的藝術(shù)品。每當(dāng)有人出價(jià)更高,系統(tǒng)都會立即通知你。這個(gè)實(shí)時(shí)更新機(jī)制使你可以做出快速反應(yīng)。這種模式,在軟件開發(fā)中稱為觀察者模式,是一種廣泛應(yīng)用于實(shí)現(xiàn)事件驅(qū)動系統(tǒng)的設(shè)計(jì)模式。 觀察者模式(Observer Pattern)是一種行為型

    2024年02月03日
    瀏覽(18)
  • java設(shè)計(jì)模式-觀察者模式(jdk內(nèi)置)

    上一篇我們學(xué)習(xí)了 觀察者模式。 觀察者和被觀察者接口都是我們自己定義的,整個(gè)設(shè)計(jì)模式我們從無到有都是自己設(shè)計(jì)的,其實(shí),java已經(jīng)內(nèi)置了這個(gè)設(shè)計(jì)模式,我們只需要定義實(shí)現(xiàn)類即可。 下面我們不多說明,直接示例代碼,例子依然同 觀察者模式篇章,建議先去看看。

    2024年02月15日
    瀏覽(24)
  • Java設(shè)計(jì)模式系列--觀察者模式寫法2:JDK

    Java設(shè)計(jì)模式系列--觀察者模式寫法2:JDK

    原文網(wǎng)址:Java設(shè)計(jì)模式系列--觀察者模式寫法2:JDK_IT利刃出鞘的博客-CSDN博客 說明 本文用示例介紹觀察者模式的一種寫法:JDK。 JDK的觀察者模式簡介 在 Java 中,java.util.Observable 類和 java.util.Observer 接口定義了觀察者模式,只要實(shí)現(xiàn)這兩個(gè)接口就可以編寫觀察者模式。 1. Ob

    2024年02月13日
    瀏覽(23)
  • 【設(shè)計(jì)模式】Head First 設(shè)計(jì)模式——觀察者模式 C++實(shí)現(xiàn)

    設(shè)計(jì)模式最大的作用就是在變化和穩(wěn)定中間尋找隔離點(diǎn),然后分離它們,從而管理變化。將變化像小兔子一樣關(guān)到籠子里,讓它在籠子里隨便跳,而不至于跳出來把你整個(gè)房間給污染掉。 主題對象(出版者)管理某些數(shù)據(jù),當(dāng)主題內(nèi)的數(shù)據(jù)改變,就會通知觀察者(訂閱者)。

    2024年02月10日
    瀏覽(28)
  • 「觀察者(Observer)」設(shè)計(jì)模式 Swift實(shí)現(xiàn)

    「觀察者(Observer)」設(shè)計(jì)模式 Swift實(shí)現(xiàn)

    觀察者設(shè)計(jì)模式(Observer Pattern)是一種行為型設(shè)計(jì)模式,它定義了對象之間的一種一對多的依賴關(guān)系,使得當(dāng)一個(gè)對象的狀態(tài)發(fā)生變化時(shí),所有依賴于它的對象都會受到通知并自動更新。 在這種模式中,被觀察者對象(Subject)存儲其觀察者對象(Observer)列表,并提供了用

    2024年02月16日
    瀏覽(25)
  • Go和Java實(shí)現(xiàn)觀察者模式

    在監(jiān)控系統(tǒng)中,我們需要采集監(jiān)控指標(biāo)的信息,假設(shè)當(dāng)采集的指標(biāo)信息超過閾值時(shí)我們需要對該監(jiān)控指標(biāo)持久化到 數(shù)據(jù)庫中并且進(jìn)行告警。 本文通過指標(biāo)采集持久化和告警來說明觀察者模式的使用,使用Go語言和Java語言實(shí)現(xiàn)。 觀察者模式是一種行為型設(shè)計(jì)模式,它定義了一

    2024年02月16日
    瀏覽(18)
  • 設(shè)計(jì)模式——觀察者模式

    設(shè)計(jì)模式——觀察者模式

    觀察者模式可以分為觀察者和被觀察者,觀察者通過注冊到一個(gè)被觀察者中,也可視為訂閱,當(dāng)被觀察者的數(shù)據(jù)發(fā)生改變時(shí),會通知到觀察者,觀察者可以據(jù)此做出反應(yīng)。 可以類比訂閱報(bào)紙,報(bào)社就是被觀察者,訂閱者就是觀察者,訂閱者通過訂閱報(bào)紙與報(bào)社建立聯(lián)系,而報(bào)

    2024年02月15日
    瀏覽(18)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包