【16】设计模式之-----观察者模式

一:定义

定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动刷新。

使用观察者模式的情况:

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

2)        当对一个对象的改变需要同时改变其它对象而不知道具体有多少对象有待改变。

3)        当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之你不希望这些对象是紧密耦合的。


二:代码实现

代码实现,JDK中提供了观察者的实现。

首先定义一个目标类,继承java.util.Observable

import java.util.Observable;

/**
 * 天气目标的具体实现类
 */
public class ConcreteWeatherSubject extends Observable {
	//天气情况的内容;
	private String content;

	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
		//天气情况有了,就要通知所有的观察者;
		//注意在通知之前,在用java中的Observer模式时候,下面这句话不可少;
		this.setChanged();
		//然后主动通知,这里我们先用推的方式;
		this.notifyObservers(content);
		//如果是拉的方式,我们就调用如下:
		//this.notifyObservers();
	}
	
}
然后定义 观察者 类,实现java.util.Observer类

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

/**
 * 具体的观察者对象;
 */
public class ConcreteObserver implements Observer {
	//定义观察者名称的变量;
	private String observerName;
	
	@Override
	public void update(Observable o, Object arg) {
		//第一种是推的方式
		System.out.println(observerName+",收到了消息,目标推送过来的是:"+arg);
		//第二种是拉的方式
		//System.out.println(observerName+"收到了消息,主动到目标对象中去拉,拉的内容是:"
		//+((ConcreteWeatherSubject)o).getContent());
	}

	public String getObserverName() {
		return observerName;
	}

	public void setObserverName(String observerName) {
		this.observerName = observerName;
	}
	

}
测试类:

/**
 *测试类
 */
public class Client {

	public static void main(String[] args) {
		//创建天气作为一个目标,也可以说是被观察者
		ConcreteWeatherSubject subject = new ConcreteWeatherSubject();
		//创建黄明的女朋友作为观察者
		ConcreteObserver girl = new ConcreteObserver();
		girl.setObserverName("黄明的女朋友");
		//创建黄明的老妈作为观察者
		ConcreteObserver mum = new ConcreteObserver();
		mum.setObserverName("黄明的老妈");
		//注册观察者
		subject.addObserver(girl);
		subject.addObserver(mum);
		//目标更新天气情况了
		subject.setContent("天气晴,气温28度");
	}

}
输出结果:





--------------------------------------------------------------------------下面是自己实现的观察者模式,并实现区别对待观察者-----------------------------------------------------------------------------
首先定义目标接口类及其实现类:
import java.util.ArrayList;
import java.util.List;

/**
 */
public abstract class WeatherSubject {
	//用来保存注册的观察者对象;
	public List<Observer> observers = new ArrayList<Observer>();
	
	//attach detach notifyObservers
	//把订阅天气的人/观察者添加到订阅者列表中
	public void attach(Observer observer){
		observers.add(observer);
	}
	
	//删除集合中指定的订阅天气的人
	public void detach(Observer observer){
		observers.remove(observer);
	}
	
	protected abstract void notifyObservers();
}
public class ConcreteWeatherSubject extends WeatherSubject {
	//晴天    下雨      下雪
	//目标对象的状态
	private String weatherContent;

	@Override
	protected void notifyObservers() {
		//循环所有注册的观察者
		for(Observer observer : observers){
			//规则是:
			//黄明的女朋友需要“下雨”的条件通知,其他的条件不通知;
			//黄明的老妈需要“下雨”或者“下雪”的条件通知,其他的条件不通知
			
			//1.如果天气是晴天,do nothing
			
			//2.如果天气是下雨
			if("下雨".equals(this.getWeatherContent())){
				if("黄明的女朋友".equals(observer.getObserverName())){
					observer.update(this);
				}
				if("黄明的老妈".equals(observer.getObserverName())){
					observer.update(this);
				}
			}
			
			//3.如果天气是下雪
			if("下雪".equals(this.getWeatherContent())){
				if("黄明的老妈".equals(observer.getObserverName())){
					observer.update(this);
				}
			}

		}
		
	}

	public String getWeatherContent() {
		return weatherContent;
	}

	public void setWeatherContent(String weatherContent) {
		this.weatherContent = weatherContent;
		this.notifyObservers();
	}
	
}
下面是观察者接口类和具体实现类:
//定义一个更新的接口方法给那些在目标方法发生改变的时候被通知的观察者对象调用
public interface Observer {
	//更新的接口
	public void update(WeatherSubject subject);
	
	//设置观察者名称;
	public void setObserverName(String observerName);
	
	//取得观察者名称
	public String getObserverName();
}
public class ConcreteObserver implements Observer {
	//观察者名称
	private String observerName;
	//天气情况的内容
	private String weatherContent;
	//提醒的内容
	private String remindThing;

	@Override
	public void update(WeatherSubject subject) {
		weatherContent = ((ConcreteWeatherSubject)subject).getWeatherContent();
		System.out.println(observerName+"收到了"+weatherContent+","+remindThing);
	}

	@Override
	public void setObserverName(String observerName) {
		this.observerName = observerName;
	}

	@Override
	public String getObserverName() {
		return observerName;
	}

	public String getWeatherContent() {
		return weatherContent;
	}

	public void setWeatherContent(String weatherContent) {
		this.weatherContent = weatherContent;
	}

	public String getRemindThing() {
		return remindThing;
	}

	public void setRemindThing(String remindThing) {
		this.remindThing = remindThing;
	}
	

}

下面为测试类:
public class Client {

	public static void main(String[] args) {
		//1.创建目标
		ConcreteWeatherSubject weatherSubject = new ConcreteWeatherSubject();
		
		//2.创建观察者
		ConcreteObserver observerGirl = new ConcreteObserver();
		observerGirl.setObserverName("黄明的女朋友");
		observerGirl.setRemindThing("下雨了,安静的待在家里吧");
		
		ConcreteObserver observerMum = new ConcreteObserver();
		observerMum.setObserverName("黄明的老妈");
		observerMum.setRemindThing("不管下雨还是下雪,我都不出门");
		
		//注册观察者
		weatherSubject.attach(observerGirl);
		weatherSubject.attach(observerMum);
		
		//目标发布天气了
		//weatherSubject.setWeatherContent("下雨");
		weatherSubject.setWeatherContent("下雪");
	}

}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值