当前位置: 首页 >  网技达人 >  观察者模式(Observer Pattern)

观察者模式(Observer Pattern)

导读:一、模式动机.观察者模式用于描述对象之间的依赖关系,它引入了观察者和观察目标两类不同的角色,由于提供了抽象层,它使得增加新的观察者和观察目标都很方便。观察者模式广泛应用于各种编程语言的事件处理模型中,Java语言也提供了对观察者模式的全面支持。.一个对象的状态或行为的变化将导致其

一、模式动机

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

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

二、模式定义

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

三、模式结构

抽象目标类

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

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

具体目标类

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

抽象观察者类

public interface Observer {
    public void update();
}

具体观察者类

public class ConcreteObserver implements Observer {

    public void update() {
        ……
    }
}

四、案例实现

案例背景

股票

案例结构

代码实现

抽象目标类:股票

public interface Stocks {

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

}

目标类:股票

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%!!");
        }
    }
}

抽象观察者类

public interface Observer {

    void upDate();

}

具体观察者类A

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

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

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());
    }
}

测试类

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

六、总结

模式优点

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

模式缺点

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

使用情形

  • 一个抽象模型有两个方面,其中一个方面依赖于另一个方面,将这两个方面封装在独立的对象中使它们可以各自独立地改变和复用
  • 一个对象的改变将导致一个或多个其他对象发生改变,且并不知道具体有多少对象将发生改变,也不知道这些对象是谁
  • 需要在系统中创建一个触发链
内容
  • 最新消息,powershell,10多年的癌症被治好了!
    最新消息,powershell,
    2023-12-10
    问:癌症是指什么?.答:.powershell一直有个特性,它的管道会传递对象,请看:.‘abc’ | ForEach-
  • RocketMQ消费者是如何负载均衡的
    RocketMQ消费者是如何负载
    2023-12-09
    摘要:RocketMQ 支持两种消息模式:集群消费( Clustering )和广播消费( Broadcasting )
  • Three.js教程:对象克隆、复制
    Three.js教程:对象克隆、
    2023-12-08
    推荐:将 NSDT场景编辑器 加入你的3D工具链.其他系列工具: NSDT简石数字孪生.对象克隆.clone()和复制.
  • FlashDuty Changelog 2023-09-07 | 新增深色模式与主题配置
    FlashDuty Change
    2023-12-04
    FlashDuty:一站式告警响应平台,前往此地址免费体验!.FlashDuty.现在已经全面支持了深色模式,这为您提供
  • 园林生态环境保护工程
    园林生态环境保护工程
    2024-01-15
    园林生态环境保护工程.园林生态环境保护工程是指利用园林绿化,改善城市环境和生态空间,保护生物多样性,**生态平衡,促进循
  • 水景工程设计与建设服务
    水景工程设计与建设服务
    2023-12-16
    水景工程设计与建设服务.水景工程作为城市绿化的一部分,已经成为城市建设的热点之一。水景工程设计与建设服务是为了满足这一需
  • 西式庭院设计与施工
    西式庭院设计与施工
    2024-01-15
    西式庭院设计与施工.西式庭院设计与施工在当今社会越来越受到人们的重视,并成为了人们追求舒适生活的重要一环。一个精心设计、
  • 工业园区景观绿化设计与施工
    工业园区景观绿化设计与施工
    2023-12-11
    工业园区景观绿化设计与施工.工业园区作为大型的工业生产基地和企业集聚区,其景观绿化设计与施工至关重要。一方面,良好的景观
  • 绿化工程设计与施工
    绿化工程设计与施工
    2023-12-06
    绿化工程设计与施工.绿化工程是城市环境建设中重要的一部分,它不仅美化了城市环境,还有利于改善空气质量,降低城市的温度,提
  • 水系景观设计与生态修复
    水系景观设计与生态修复
    2024-01-10
    水系景观设计与生态修复.水系景观设计与生态修复是当下社会持续关注的热点话题。随着城市发展和环境污染不断加剧,人们对自然环
  • 商业综合体景观规划与绿化设计
    商业综合体景观规划与绿化设计
    2024-01-05
    商业综合体景观规划与绿化设计.商业综合体是城市中的重要组成部分,它不仅仅是商业活动的聚集地,更是城市的新地标和休闲娱乐中
  • 室外园林装饰艺术品**
    室外园林装饰艺术品**
    2024-01-05
    室外园林装饰艺术品**.室外园林装饰艺术品是指用于室外环境中装饰和美化园林景观的各种艺术品和装饰品。这些艺术品可以包括雕
  • 植物种植及养护服务
    植物种植及养护服务
    2024-01-10
    植物种植及养护服务.植物种植及养护服务在现代社会越来越受到人们的重视。随着城市化的不断发展,城市绿化成为人们关注的焦点之
  • 园林绿化维护管理
    园林绿化维护管理
    2024-01-05
    园林绿化维护管理.园林绿化是城市环境中不可或缺的一部分,它不仅美化了城市的面貌,还起到了调节气候、净化空气、增加人们的休