学习笔记之观察者模式

学习笔记之观察者模式

首先要简单举个例子认识一下观察者模式

例:对于现实生活中出版者和订阅者之间的事情

1.报社的业务就是出版报纸

2.向某家报社订阅报纸,只要他们有新报纸出版,就会给你送来。只要你是他们的订户,你就会已知收到新报纸。

3.当你不想再看报纸的时候,取消订阅,他们就不会再送新报纸来

4.只要报社还在运营,就会一直有人(或单位)向他们订阅包子或取消订阅

从这个例子中我们思考一下:报社一有新的报纸就会送给订报者,报社可以有多个订报者也就是一对多的依赖关系。当订报者取消订阅后报社就不再向他推送报纸。所以订报者可以动态的选择订阅或取消订阅。我们可以把报社称为一个主题,订报者称为观察者,报社有新的报纸时发布时所有的订报者便会收到最新的报纸,也就是主题一有改变所有的观察者都会更新状态。这个例子就相当于一个观察者模式。

通过这个例子我们总结出:出版者+订阅者=观察者模式

接下来展示几张图片大家会更加理解观察者模式:

 




 

看完这两个例子我们脑子中应该已经有一个对观察者模式比较形象的理解,下来来说一下观察者模式的定义

观察者模式:定义对象之间的一对多依赖,当一个对象改变状态时,他的所有依赖者都会收到同绘制并自动更新。

下面我们以气象监测应用的例子进行类图及代码深入理解观察者模式

 

对于这个例子我们思考该怎样或观察者模式的类图

 

从这个图中我们可以看出松耦合的威力

关于观察者的一切,主题只知道观察者实现了某个接口(也就是Observer接口)。主题不需要知道观察者的具体类是谁,做了些什么或其他任何细节

任何时候我们都可以增加新的观察者。因为主题唯一依赖的东西是一个实现Observer接口的对象列表,所以我们可以随时增加观察者。事实上,在运行时我们可以用新的观察者取代现有的观察者,主题不会受到任何影响。同样的,也可以在任何时候删除某些观察者

有新类型的观察者出现时,主题的代码不需要修改。假如我们有个新的具体类需要当观察者,我们不需要为了兼容新类型而修改主题的代码,所有要做的就是在新的类里实现此观察者接口,然后注册为观察者即可。主题不在乎别的,它只会发送通知给所有实现了此观察者接口的对象。

我们可以独立的复用主题或观察者。如果我们在其他地方需要使用主题或观察者,可以轻易的复用,因为二者并非紧密耦合。

改变主题或观察者其中一方,并不会影响另一方。因为二者是松耦合的,所以只要他们之间的接口仍被遵守,我们就可以自由的改变他们

这也体现了模式设计的原则:为了交互对象之间的松耦合设计而努力

这样我们就可以清楚的知道观

察者模式的优点,它提供了一种对象设计,让主题和观察者之间松耦合,他们依然可以交互,但是不太清楚彼此的细节

松耦合的设计之所以让我们建立有弹性的OO系统,能够应对变化,是因为对象之间的互相依赖降到了最低。

package observer.allinterfcae;

public interface Subject {
	public void notifyObserver();
	public void registerObserver(Observer o);
	public void removeObserver(Observer o);
}


package observer.allinterfcae;

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


package observer.allinterfcae;

public interface DisplayElement {
	public void display();
}

package observer.allinterfcae;

import java.util.ArrayList;

public class WeatherData implements Subject {
	private ArrayList
   
   
    
     observers;
	private float temperature;
	private float humidity;
	//构造函数
	public WeatherData(){
		observers=new ArrayList
    
    
     
     ();
	}
	//public 
	@Override
	//注册对象
	public void registerObserver(Observer o) {
		// 把参数Observer o注册注册进数组里面
		observers.add(o);
	}
	//删除对象
	@Override
	public void removeObserver(Observer o) {
		//获取索引
		int i = observers.indexOf(o);
		if (i >= 0) {
			observers.remove(i);
		}
	}
	
	@Override
	public void notifyObserver() {
		//把状态告诉每一个观察者,因为观察者都实现了updata()方法
		for (Observer observer : observers) {
			observer.update(temperature, humidity);
		}
	}
	//当有数据更新时通知观察者
	 public void measurementsChanged(){
		 notifyObserver();
	 }
	 //用来测试数据
	 public void setMeasurements(float temperature,float hunmidity){
		 this.temperature=temperature;
		 this.humidity=hunmidity;
		 measurementsChanged();
	 }

}



package observer.allinterfcae;

public class CurrentConditionDisplay implements Observer, DisplayElement {
	private float temperature;
	private float humidity;
	private Subject weatherData;
	//构造器需要weatherData对象,作为注册用
	public CurrentConditionDisplay(WeatherData weatherdata) {
		this.weatherData=weatherData;
		weatherdata.registerObserver(this);
	}
	@Override
	public void display() {
		System.out.println("Current condition:"+temperature+"F degree and"+humidity+"% humdity");
	}

	@Override
	public void update(float temperature, float humidity) {
		this.temperature=temperature;
		this.humidity=humidity;
		display();
	}

}

package observer.allinterfcae;

public class Test {

	public static void main(String[] args) {
		WeatherData weatherData=new WeatherData();
		CurrentConditionDisplay currentDisplay=new CurrentConditionDisplay(weatherData);
		System.out.println("WeatherStation:");
		weatherData.setMeasurements(80, 65);
		weatherData.setMeasurements(82, 70);
		weatherData.setMeasurements(78, 90);
	}
}


    
    
   
   

 

通过代码几乎已经掌握的观察者模式使用方式,但是我们可以看到上述代码是通过主题向观察者强迫式的推送所有数据,但观察者不一定愿意接受所有数据我们还可以通过“拉”的方式让观察者接收自己想要的数据,因为所有未来可能还会增多,而每个报告版不一定要用到所有数据

接下来通过使用java内置的观察者模式运行代码这次运用“拉”数据的方式

首先我们需要运用类图更好的了解java内置观察者模式运作过程


我们可以看到java内置的

观察者模式中主题是一个类,所以需要WeatherData继承Observble,确实这有点违反设计原则中面向接口编程而不面向过程编程的原则。所以如果需要你可以自己写主题,并且不是很麻烦就像前面的代码一样。

 

package wetherobserver;

public interface DisplayElement {
	public void display();
}


package wetherobserver;

import java.util.Observable;

public class WeatherData extends Observable{
	private float tempreature;
	private float humidity;
	//构造方法
	public WeatherData() {}
	public void measurementsChanged(){
		//将changed的值设置为true
		setChanged();
		//把状态告诉每一位观察者
		notifyObservers();
	}
	public void setMeasurements(float tempreature,float humidity){
		this.tempreature=tempreature;
		this.humidity=humidity;
		measurementsChanged();
	}
	public float getTempreature(){
		return tempreature;
	}
	public float getHumidity(){
		return humidity;
	}
}


package wetherobserver;

import java.util.Observable;
import java.util.Observer;

public class CurrentConditionDisplay implements Observer,DisplayElement{
	private float temperature;
	private float humidity;
	Observable observable;
	public CurrentConditionDisplay(Observable observable) {
		this.observable=observable;
		observable.addObserver(this);
	}
	@Override
	public void update(Observable obs, Object arg) {
		if(obs instanceof WeatherData){
			WeatherData weatherData=(WeatherData) obs;
			this.temperature=weatherData.getTempreature();
			this.humidity=weatherData.getHumidity();
			display();
		}
	}
	@Override
	public void display() {
		System.out.println("Current condition:"+temperature+"F degree and"+humidity+"% humdity");
	}

}


package wetherobserver;

public class Test {
	public static void main(String[] args) {
		WeatherData weatherData=new WeatherData();
		CurrentConditionDisplay currentDisplay=new CurrentConditionDisplay(weatherData);
		System.out.println("Current WeatherStation:");
		weatherData.setMeasurements(80, 65);
		weatherData.setMeasurements(82, 70);
		weatherData.setMeasurements(78, 90);
	}
}


 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1) 优秀的程序应该是这样的:阅读时,感觉很优雅;新增功能时,感觉很轻松;运行时,感觉很快速,这就需要设计模式支撑。2) 设计模式包含了大量的编程思想,讲授和真正掌握并不容易,网上的设计模式课程不少,大多讲解的比较晦涩,没有真实的应用场景和框架源码支撑,学习后,只知其形,不知其神。就会造成这样结果: 知道各种设计模式,但是不知道怎么使用到真实项目。本课程针对上述问题,有针对性的进行了升级 (1) 授课方式采用 图解+框架源码分析的方式,让课程生动有趣好理解 (2) 系统全面的讲解了设计模式,包括 设计模式七大原则、UML类图-类的六大关系、23种设计模式及其分类,比如 单例模式的8种实现方式、工厂模式的3种实现方式、适配器模式的3种实现、代理模式的3种方式、深拷贝等3) 如果你想写出规范、漂亮的程序,就花时间来学习设计模式吧课程内容和目标本课程是使用Java来讲解设计模式,考虑到设计模式比较抽象,授课采用 图解+框架源码分析的方式1) 内容包括: 设计模式七大原则(单一职责、接口隔离、依赖倒转、里氏替换、开闭原则、迪米特法则、合成复用)、UML类图(类的依赖、泛化和实现、类的关联、聚合和组合) 23种设计模式包括:创建型模式:单例模式(8种实现)、抽象工厂模式、原型模式、建造者模式、工厂模式。结构型模式:适配器模式(3种实现)、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式(3种实现)。行为型模式:模版方法模式、命令模式、访问者模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式(Interpreter模式)、状态模式、策略模式、职责链模式(责任链模式)2) 学习目标:通过学习,学员能掌握主流设计模式,规范编程风格,提高优化程序结构和效率的能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值