Java微服务-设计模式系列全套文章-观察者模式(Observer Pattern)

createh51个月前 (02-01)技术教程11

一、模式动机

观察者模式用于描述对象之间的依赖关系,它引入了观察者和观察目标两类不同的角色,由于提供了抽象层,它使得增加新的观察者和观察目标都很方便。观察者模式广泛应用于各种编程语言的事件处理模型中,Java语言也提供了对观察者模式的全面支持。

  • 一个对象的状态或行为的变化将导致其他对象的状态或行为也发生改变,它们之间将产生联动
  • 定义了对象之间一种一对多的依赖关系,让一个对象的改变能够影响其他对象
  • 发生改变的对象称为观察目标,被通知的对象称为观察者
  • 一个观察目标可以对应多个观察者

二、模式定义

  • 观察者模式(Observer Pattern):定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新
  • 观察者模式又叫做发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式
  • 观察者模式是一种对象行为型模式

三、模式结构

抽象目标类

csharp

public abstract class Subject {
protected ArrayList observers = new ArrayList();

public void attach(Observer observer) {
        observers.add(observer);    
}
public void detach(Observer observer) {
        observers.remove(observer);    
}
public abstract void notify( );
}

具体目标类

scala

public class ConcreteSubject extends Subject {
    //实现通知方法
    public void notify() {
        for(Object obs:observers) {
            ((Observer)obs).update();
        }
    }	
}

抽象观察者类

java

public interface Observer {
    public void update();
}

具体观察者类

angelscript

public class ConcreteObserver implements Observer {

    public void update() {
        ……
    }
}

四、案例实现

案例背景

股票

案例结构

代码实现

抽象目标类:股票

java

public interface Stocks {

    ArrayList OBSERVERS = new ArrayList<>();
    void attach(Observer observer);
    void detach(Observer observer);
    void notifyInvestor();

}

目标类:股票

typescript

public class Stock implements Stocks{

    private String stockName;
    private int price;

    public Stock(String stockName, int price) {
        this.stockName = stockName;
        this.price = price;
    }

    public Stock() {

    }

    public String getStockName() {
        return stockName;
    }

    public void setStockName(String stockName) {
        this.stockName = stockName;
    }

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    @Override
    public void attach(Observer observer) {
        OBSERVERS.add(observer);
    }

    @Override
    public void detach(Observer observer) {
        OBSERVERS.remove(observer);
    }

    @Override
    public void notifyInvestor() {
        if(price >= 25*1.05 || price <= 25*0.95){
            System.out.println("通知:股票价格变动幅度超过5%!");
            for (Observer observer: OBSERVERS) {
                observer.upDate();
            }
        } else {
            System.out.println("股票价格变化幅度没有超过5%!!");
        }
    }
}

抽象观察者类

java

public interface Observer {

    void upDate();

}

具体观察者类A

typescript

public class ConcreteObserverA implements Observer {

    private String name;
    private Stock stock;

    public ConcreteObserverA(String name, Stock stock) {
        this.name = name;
        this.stock = stock;
    }

    public ConcreteObserverA(String name) {
        this.name = name;
    }

    @Override
    public void upDate() {
        System.out.println("通知"+name+":"+stock.getStockName()+"的股票价格变化幅度超过5%,股票价格为:"+stock.getPrice());
    }
}

具体观察者类B

typescript

public class ConcreteObserverB implements Observer {

    private String name;

    public ConcreteObserverB(String name, Stock stock) {
        this.name = name;
        this.stock = stock;
    }

    public ConcreteObserverB(String name) {
        this.name = name;
    }

    private Stock stock;

    @Override
    public void upDate() {
        System.out.println("通知"+name+":"+stock.getStockName()+"的股票价格变化幅度超过5%,股票价格为:"+stock.getPrice());
    }
}

具体观察者类C

typescript

public class ConcreteObserverC implements Observer {

    private String name;
    private Stock stock;

    public ConcreteObserverC(String name, Stock stock) {
        this.name = name;
        this.stock = stock;
    }

    public ConcreteObserverC(String name) {
        this.name = name;
    }

    @Override
    public void upDate() {
        System.out.println("通知"+name+":"+stock.getStockName()+"的股票价格变化幅度超过5%,股票价格为:"+stock.getPrice());
    }
}

测试类

reasonml

public class Test {

    public static void main(String[] args) {
        Stock stock1 = new Stock("股票1",25);
        System.out.println(stock1.getStockName()+"的股价为:"+stock1.getPrice());
        Observer obs1,obs2,obs3;
        obs1 = new ConcreteObserverA("smith",stock1);
        obs2 = new ConcreteObserverB("tom",stock1);
        obs3 = new ConcreteObserverC("李白",stock1);
        stock1.attach(obs1);
        stock1.attach(obs2);
        stock1.attach(obs3);
        stock1.setPrice(22);

        stock1.notifyInvestor();

    }

}

案例结果

五、模式分析

  • 有时候在具体观察者类ConcreteObserver中需要使用到具体目标类ConcreteSubject中的状态(属性),会存在关联或依赖关系
  • 如果在具体层之间具有关联关系,系统的扩展性将受到一定的影响,增加新的具体目标类有时候需要修改原有观察者的代码,在一定程度上违背了开闭原则,但是如果原有观察者类无须关联新增的具体目标,则系统扩展性不受影响

六、总结

模式优点

  • 可以实现表示层和数据逻辑层的分离
  • 在观察目标和观察者之间建立一个抽象的耦合
  • 支持广播通信,简化了一对多系统设计的难度
  • 符合开闭原则,增加新的具体观察者无须修改原有系统代码,在具体观察者与观察目标之间不存在关联关系的情况下,增加新的观察目标也很方便

模式缺点

  • 将所有的观察者都通知到会花费很多时间
  • 如果存在循环依赖时可能导致系统崩溃
  • 没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而只是知道观察目标发生了变化

使用情形

  • 一个抽象模型有两个方面,其中一个方面依赖于另一个方面,将这两个方面封装在独立的对象中使它们可以各自独立地改变和复用
  • 一个对象的改变将导致一个或多个其他对象发生改变,且并不知道具体有多少对象将发生改变,也不知道这些对象是谁
  • 需要在系统中创建一个触发链

相关文章

如何通过Serverless提高 Java 微服务治理效率?

简介: 在业务初期,因人手有限,想要快速开发并上线产品,很多团队使用单体的架构来开发。但是随着公司的发展,会不断往系统里面添加新的业务功能,系统越来越庞大,需求不断增加,越来越多的人也会加入到开发团队...

Java:Java中的微服务(java微服务包括什么)

  如果你想使用Java中的云原生微服务快速实现大规模可扩展性,那么不需要重新发明轮子。一些创新工具可以帮助你。通过Java培训课程,在Java(软件开发中最常用的编程语言)方面打下坚实的基础,更好地...

如何使用 Java 和 Docker 构建微服务

快速浏览在Java生态中,构建微服务的策略包括Container-less,Self-contained,以及In-container等。Container-less微服务将应用及其依赖打包成一个单一...

3 个主流 Java 微服务框架的特点分析

本文我们简单聊聊当下主流的 3 个 Java 微服务框架,看看各自的特点,下面和千锋广州小编一起来看看吧!1. Spring and Spring BootimageSpring Boot 在 Jav...

15年大牛用140多个实战案例深入讲解Java微服务架构文档

前言本文是由15年开发大牛用140个实战案例,完美演示Java微服务架构实战:SpringBoot +SpringCloud +Docker +RabbitMQ;用丰富的架构图示+手把手步骤学习,带领...

基于OpenTelemetry实现Java微服务调用链跟踪

本文分享自华为云社区《基于OpenTelemetry实现Java微服务调用链跟踪-云社区-华为云》,作者: 可以交个朋友。一 背景随着业务的发展,所有的系统都会走向微服务化体系,微服务进行拆分后,服务...