java设计模式之观察者模式

1,什么是观察者模式?定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动 更新自己。形象点说就像 有几个人订阅邮件一样,比如订阅腾讯新闻,腾讯新闻就是一个主题(subject),你们每一个人都是一个观察者(observer);可以取消订阅,就不是观察者了,也 可以增加一个订阅的人,这个人就成了观察者,一般观察者有以下几个角色:


  1, 抽象主题(Subject)角色:抽象主题角色把所有对观察者对象的引用保存在一个聚集(比如ArrayList对象)里,每个主题都可以有任何数量的观察者。
  抽象主题提供一个接口,可以增加和删除观察者对象,抽象主题角色又叫做抽象被观察者(Observable,jdk自带的观察者模式实现,用的是这个词,不过我们最好统一用Subject这个词)角色
  2, 具体主题(ConcreteSubject)角色:将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。
  具体主题角色又叫做具体被观察者(Concrete Observable)角色
 
  3, 抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在得到主题的通知时更新自己,这个接口叫做更新接口
  4, 具体观察者(ConcreteObserver)角色:存储与主题的状态自恰的状态。具体观察者角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态 像协调。

  如果需要,具体观察者角色可以保持一个指向具体主题对象的引用。


首先定抽象主题角色:Subject.java


package observer;
/**
 * 抽象主题角色
 * @author yt
 *
 */
public interface Subject {
	/**
	 * 向主题注册观察者
	 * @param o
	 * @author mj
	 */
	public void registerObserver(Observer o);
	
	/**
	 * 从主题中删除观察者
	 * @param o
	 * @author mj
	 */
	public void removeObserver(Observer o);
	
	/**
	 * 
	 * 通知观察者
	 * @author mj
	 */
	public void notifyObservers();
}


再定义具体主题角色 TencentSubject.java


package observer;

import java.util.ArrayList;
import java.util.List;

/**
 * 腾讯新闻这个主题
 * @author yt
 *
 */
public class TencentSubject implements Subject {
	
	//主题中要持有所有的观察者,观察这都要被注册到主题中的这个list中
	private List<Observer> list=new ArrayList<>();
	
	//标题和内容,为了观察者能够 使用拉模式(pull)获取自己需要的信息(比如只获取标题,或者只获取内容,或者都获取),提供这两个变量的get/set方法
	private String title;
	private String content;
	
	@Override
	public void registerObserver(Observer o) {
		list.add(o);//注册观察者
	}

	@Override
	public void removeObserver(Observer o) {
		list.remove(o);//删除观察者

	}

	@Override
	public void notifyObservers() {
		for(Observer o:list){
			o.update(title, content);//推模式
			//o.update(this); //拉模式
		}

	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
	}
	
	
	

}

定义抽象观察者角色  Observer.java


package observer;
/**
 * 抽象的观察者角色
 * @author yt
 * 观察者订阅新闻又分为两种,推送模式(push),和拉取模式(pull)
 */
public interface Observer {
	/**
	 * 1,推送模式,不管观察者需不需要,一股脑的全推送给观察者。
	 * 观察者向主题订阅自己感兴趣的内容。这里以订阅新闻为列子,当有新的新闻时,主题把 标题,和内容推送给观察者。
	 * @param title
	 * @param content
	 * @author mj
	 */
	public void update(String title,String content);
	
	/**
	 * 拉取(pull)模式,一般把主题对象传过来,观察这,根据需要到主题中拉取自己需要的内容,而不是被动的接受 主题推送过来的。
	 * @param subject
	 * @author mj
	 */
	public void update(Subject subject);
}

定义具体观察者角色 ZhangsanObserver.java


package observer;
/**
 * 观察者张三
 * @author yt
 *
 */
public class ZhangsanObserver implements Observer {
	
	/**
	 * 推模式
	 */
	@Override
	public void update(String title, String content) {
		System.out.println("我是观察者zhangsan收到的推送消息为:"+title+":"+content);

	}
	
	/**
	 * 拉模式
	 */
	@Override
	public void update(Subject subject) {
		System.out.println("我是观察者zhangsan收到的推送消息为:"+((TencentSubject)subject).getTitle());
		
	}

}

定义具体观察者角色 LishiObserver.java


package observer;
/**
 * 观察者张三
 * @author yt
 *
 */
public class LishiObserver implements Observer {
	
	/**
	 * 推模式
	 */
	@Override
	public void update(String title, String content) {
		System.out.println("我是观察者lishi收到的推送消息为:"+title+":"+content);

	}
	
	/**
	 * 拉模式
	 */
	@Override
	public void update(Subject subject) {
		System.out.println("我是观察者lishi收到的推送消息为:"+((TencentSubject)subject).getTitle());
		
	}

}

客户端调用


package observer;

public class ClientObserver {
	public static void main(String[] args) {
		//创建主题对象
		TencentSubject subject=new TencentSubject();
		//创建观察者对象
		ZhangsanObserver zhangsan=new ZhangsanObserver();
		LishiObserver lishi=new LishiObserver();
		//把观察者注册到主题TencentSubject中
		subject.registerObserver(zhangsan);
		subject.registerObserver(lishi);
		//当主题对象改变时(有新的新闻产生时)
		subject.setTitle("美国大选");
		subject.setContent("特朗普当选为美国总统!");
		subject.notifyObservers();//还可以在这个方法中再添加一些逻辑,比如当满足某一条件时,再推送。
	}
}

输出:

我是观察者zhangsan收到的推送消息为:美国大选:特朗普当选为美国总统!
我是观察者lishi收到的推送消息为:美国大选:特朗普当选为美国总统!


二:jdk自带的观察者模式实现。

 jdk 提供了 Observerable /Observer 实现,Observerable 相当于本列的 Subject 只不过他是一个类,而不是一个接口,当需要多继承的时候就没法了,所以说有一定的缺陷。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值