Java设计模式(十五)之行为型模式:观察者模式

Java设计模式(十五)之行为型模式:观察者模式

一、定义:

观察者模式中,观察者模式定义了对象之间的一对多依赖关系,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并且自动更新。   在这里,发生改变的对象称之为观察目标,而被通知的对象称之为观察者。一个观察目标可以对应多个观察者,而且这些观察者之间没有相互联系,所以么可以根据需要增加和删除观察者,使得系统更易于扩展。

观察者模式又称为发布-订阅模式。

UML结构图:

Java设计模式(十五)之行为型模式:观察者模式

该模式包含四个角色:

(1)Subject:抽象主题(被观察者)。他把所有对观察者对戏的引用保存在一个集合里,每一个主题都可以有多个观察者。被观察者提供一个接口,可以增加和删除观察者角色。一般用一个抽象类和接口来实现。

(2)Observer:抽象观察者。为所有的具体观察者定义一个接口,在得到主题的通知时能够及时的更新自己

(3)ConcreteSubject:具体主题。将有关状态存入具体观察者对象。在具体主题发生改变时,给所有的观察者发出通知。

(4)ConcreteObserver:具体观察者。实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态相协调。如果需要,具体观察者角色可以保存一个指向具体主题角色的引用。

 

二、实现观察者模式:

情景是这样的:在气象观测站中,它能够追踪目前的天气状况,包括温度、适度、气压。需要实现一个布告板,能够分别显示目前的状态,气象统计和简单的预报。当气象站中获取最新的测量数据时,三种布告板必须实时更新。

        下面是这个案例的设计图:

Java设计模式(十五)之行为型模式:观察者模式

编码实现:

主题接口   Subject.java

public interface Subject {
	/**
	 * 注册观察者
	 * @param observer
	 */
	public void registerObserver(Observer observer);
	
	/**
	 * 删除观察者
	 * @param observer
	 */
	public void removeOberver(Observer observer);
	
	/**
	 * 当主题状态发生改变时,这个方法需要被调用,以通知所有观察者
	 */
	public void notifyObserver();
}

观察者接口  Observer.java

public interface Observer {
	public void update(float temp,float humidity,float pressure);
}

布告板显示接口 DisplayElement.java

public interface DisplayElement {
	public void display();
}

WeatherData实现主题接口 WeatherData.java

public class WeatherData implements Subject{
	private List<Observer> observers;
	private float tempterature;
	private float pressure;
	private float humidity;
	
	public WeatherData(){
		observers = new ArrayList<Observer>();
	}
	
	@Override
	public void notifyObserver() {
		for(int i = 0; i < observers.size();i++){
			Observer observer = observers.get(i);
			observer.update(tempterature, humidity, pressure);
		}
	}
 
	@Override
	public void registerObserver(Observer observer) {
		observers.add(observer);
	}
 
	@Override
	public void removeOberver(Observer observer) {
		int i = observers.indexOf(observer);
		if(i >= 0){
			observers.remove(i);
		}
	}
 
	/**
	 * 气象站得到更新的观测数据时,通知观察者
	 */
	public void measurementChanged(){
		notifyObserver();
	}
	
	public void setMeasurements(float temperature,float humidity,float pressure){
		this.tempterature = temperature;
		this.humidity = humidity;
		this.pressure = pressure;
		measurementChanged();
	}
}

布告板  CurrentCondituonDisplay.java

public class CurrentConditionsDisplay implements Observer,DisplayElement{
	private float temperature;
	private float humidity;
	private	Subject weatherData;
	
	public CurrentConditionsDisplay(Subject weatherData){
		this.weatherData = weatherData;
		weatherData.registerObserver(this);      //注册观察者
	}
	
	public void update(float temp, float humidity, float pressure) {
		this.temperature = temp;
		this.humidity = humidity;
		display();
	}
 
	@Override
	public void display() {
		System.out.println("Current conditions:"+temperature+"F degrees and "+humidity+"% humidity");
	}
 
}

测试程序  WeatherStation

public class WeatherStation {
 
	public static void main(String[] args) {
		WeatherData weatherData = new WeatherData();
		
		CurrentConditionsDisplay conditionsDisplay = new CurrentConditionsDisplay(weatherData);
	
		weatherData.setMeasurements(80, 65, 30.4f);
		weatherData.setMeasurements(82, 70, 29.2f);
		weatherData.setMeasurements(78, 78, 40.4f);
	}
}

运行结果:

Java设计模式(十五)之行为型模式:观察者模式

 

 

三、观察者模式小结:

1、观察者模式的两种模式:
观察者模式在关于目标角色、观察者角色通信的具体实现中,有两个版本:

(1)一种情况便是目标角色在发生变化后,仅仅告诉观察者角色“我变化了”,观察者角色如果想要知道具体的变化细节,则就要自己从目标角色的接口中得到。这种模式被很形象的称为:拉模式——就是说变化的信息是观察者角色主动从目标角中“拉”出来的。

(2)还有一种方法,那就是我目标角色“服务一条龙”,通知你发生变化的同时,通过一个参数将变化的细节传递到观察者角色中去。这就是“推模式”——管你要不要,先给你啦。

这两种模式的使用,取决于系统设计时的需要。如果目标角色比较复杂,并且观察者角色进行更新时必须得到一些具体变化的信息,则“推模式”比较合适。如果目标角色比较简单,则“拉模式”就很合适啦。

2、优点:

(1)当两个对象之间松耦合,他们依然可以交互,但是不太清楚彼此的细节。观察者模式提供了一种对象设计,让主题和观察者之间松耦合。主题所知道只是一个具体的观察者列表,每一个具体观察者都符合一个抽象观察者的接口。主题并不认识任何一个具体的观察者,它只知道他们都有一个共同的接口。

(2)观察者模式支持“广播通信”。主题会向所有的观察者发出通知。

(3)观察者模式符合“开闭原则”的要求。

3、缺点:

(1)如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。

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

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

4、适用场所:

(1)一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将二者封装在独立的对象中使它们可以各自独立地改变和复用。

(2)一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。

(3)一个对象必须通知其他对象,而并不知道这些对象是谁。需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。换言之, 你不希望这些对象是紧密耦合的。

 

原博客链接:

https://blog.csdn.net/chenssy/article/details/8955696

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/100068.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • word怎么把编号变成文本格式_word字离序号特别远

    word怎么把编号变成文本格式_word字离序号特别远记录一下word如何去掉自动编号格式但保留原编号内容的方法:1.调出word的“开发工具”选项打开文件->选项->自定义功能区->选中开发工具->确定,2.编写宏依次点击:开发工具-宏-在“宏名”框内输入宏名(如:NumToTxt)-单击“创建”按钮,弹出VisualBasic编辑器窗口,窗口内自动出现以下内容把下面的这段代码复制下来:ActiveDocument.Content.ListFormat.ConvertNumbersToText粘.

    2025年6月2日
    2
  • k8s安装使用_setup error怎么解决

    k8s安装使用_setup error怎么解决安装GPG秘钥:curlhttps://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg|sudoapt-keyadd-错误消失

    2022年10月10日
    2
  • ac测评题库_队长小翼剧场版

    ac测评题库_队长小翼剧场版给定一个 N×M 的棋盘,有一些格子禁止放棋子。问棋盘上最多能放多少个不能互相攻击的骑士(国际象棋的“骑士”,类似于中国象棋的“马”,按照“日”字攻击,但没有中国象棋“别马腿”的规则)。输入格式第一行包含三个整数 N,M,T,其中 T 表示禁止放置的格子的数量。接下来 T 行每行包含两个整数 x 和 y,表示位于第 x 行第 y 列的格子禁止放置,行列数从 1 开始。输出格式输出一个整数表示结果。数据范围1≤N,M≤100输入样例:2 3 0输出样例:4#include<b

    2022年8月9日
    6
  • java db4o,DB4O–java对象数据库[通俗易懂]

    java db4o,DB4O–java对象数据库[通俗易懂]特点直接存储java对象,抛弃对象映射的繁琐可以使用简单的查询语句致命缺点与java语言绑定demogitee地址https://gitee.com/ichiva/db4o-demo.git主要依赖org.fudaa.com.db4odb4o-java55.5.1编写测试用例官方实体类@DatapublicclassCar{privateIntegerid;privateString…

    2022年7月21日
    12
  • 手机抓包工具 charles使用[通俗易懂]

    手机抓包工具 charles使用[通俗易懂]转自:https://blog.csdn.net/weixin_42338923/article/details/80500323(我又添加了几句我的使用经验)1、下载charles包、安装https://www.charlesproxy.com/download/2、关闭电脑防火墙【但我的经验是:可以选择先不关闭防火墙试一试,因为我后边再次使用时没关闭防火墙也是可以抓包的)】打开…

    2022年6月6日
    32
  • 列举出linux文件和目录常用的命令_shell基本命令

    列举出linux文件和目录常用的命令_shell基本命令目录命令总览ls(英文全拼:listfiles):列出目录及文件名cd(英文全拼:changedirectory):切换目录pwd(英文全拼:printworkdirectory):显

    2022年7月29日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号