【设计模式】《Head First 设计模式》读书笔记——观察者模式

观察者模式:

定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。

涉及设计原则:

1.为了交互对象之间的松耦合设计而努力

2.找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起

3.针对接口编程,不针对实现编程

4.多用组合,少用继承

问题简单描述:

多个读者订阅同一个报社的报纸,需要实现报社没更新一版报纸,订阅的读者都会收到新的报纸。

解决思路:

报纸实现主题接口(包含添加观察者、移除观察者、通知观察者基本方法),读者实现观察者接口(包含更新基本方法)。报纸中包含观察者队列,主题和观察者形成一对多关联。报纸每发布新消息,都遍历观察者队列通知每一个观察者。读者初始化或用set方法订阅主题。

UML图:


实现代码:

主题接口

package observer;

/**
 * 主题接口
 * author terry
 *
 */
public interface Subject {
	//让观察者关注主题
	public void registObserver(Observer observer);
	
	//让观察者取消关注主题
	public void removeObserver(Observer observer);
	
	//主题修改信息,推送信息
	public void notifyObservers();
	

}

观察者接口

package observer;

/**
 * 观察者实现接口
 * @author terry
 *
 */
public interface Observer {
	//观察者接收主题消息
	public void update(NewsInfo newsInfo);
	
}

NewsInfo(模拟推送信息)

package observer;

/***
 * 主题推送内容
 * @author terry
 *
 */
public class NewsInfo {
	
	private String message;
	
	private String pic;
	
	public NewsInfo(){
		
	}

	public NewsInfo(String message, String pic) {
		super();
		this.message = message;
		this.pic = pic;
	}

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}

	public String getPic() {
		return pic;
	}

	public void setPic(String pic) {
		this.pic = pic;
	}

	@Override
	public String toString() {
		return "NewsInfo [message=" + message + ", pic=" + pic + "]";
	}
	
	
	

}

人民日报(主题实现类)

package observer;

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

/**
 * 人民日报
 * @author terry
 *
 */
public class RenMinNewspaper implements Subject {
	
	//订阅主题的观察者
	private List<Observer> observers;
	
	//消息
	private NewsInfo newsInfo;
	
	public RenMinNewspaper(){
		observers=new ArrayList<>();
	}

	@Override
	public void registObserver(Observer observer) {
		//观察者添加到list 
		observers.add(observer);
		
	}

	@Override
	public void removeObserver(Observer observer) {
		//观察者从list中移除
		int idx=observers.indexOf(observer);
		if(idx>=0){
			observers.remove(idx);
		}
		
	}

	@Override
	public void notifyObservers() {
		//通知所有观察者
		for(Observer observer:observers){
			//调用update方法(推消息是调用,如果观察者主动拉主题消息不需要调用)
			observer.update(newsInfo);
		}
	}
	
	//报社发报
	public void publishNewspaper(){
		notifyObservers();
	}
	
	

	public List<Observer> getObservers() {
		return observers;
	}

	public void setObservers(List<Observer> observers) {
		this.observers = observers;
	}

	public NewsInfo getNewsInfo() {
		return newsInfo;
	}

	public void setNewsInfo(NewsInfo newsInfo) {
		this.newsInfo = newsInfo;
		//每次修改信息时发报
		publishNewspaper();
	}
	
	

}

钱江日报(主题实现类)

package observer;

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

public class QianJiangNewspaper implements Subject{
	
	private List<Observer> observers;
	
	private NewsInfo newsInfo;
	
	public QianJiangNewspaper(){
		observers=new ArrayList<>();
	}

	@Override
	public void registObserver(Observer observer) {
		observers.add(observer);
		
	}
	
	@Override
	public void removeObserver(Observer observer) {
		int i=observers.indexOf(observer);
		if(i>=0){
			observers.remove(i);
		}
		
	}

	@Override
	public void notifyObservers() {
		for(Observer observer:observers){
			observer.update(newsInfo);
		}
		
	}
	
	public void publishNewspaper(){
		notifyObservers();
	}

	public List<Observer> getObservers() {
		return observers;
	}

	public void setObservers(List<Observer> observers) {
		this.observers = observers;
	}

	public NewsInfo getNewsInfo() {
		return newsInfo;
	}

	public void setNewsInfo(NewsInfo newsInfo) {
		this.newsInfo = newsInfo;
		publishNewspaper();
	}
	
	
	

}

Reader1(观察者实现类)


package observer;

public class Reader1 implements Observer{
	
	//消息
	private NewsInfo newsInfo;

	//主题
	private Subject subject;
	
	public Reader1(Subject subject){
		//设置主题
		this.subject=subject;
		//注册到主题
		subject.registObserver(this);
	}
	
	@Override
	public void update(NewsInfo newsInfo) {
		this.newsInfo=newsInfo;
		doReading();
	}
	
	public void doReading(){
		System.out.println("Reader1:"+newsInfo.toString());
	}

	public Subject getSubject() {
		return subject;
	}
	
	//添加主题set方法可以动态修改主题
	public void setSubject(Subject subject) {
		this.subject = subject;
		subject.registObserver(this);
	}
	
	

}

Reader2(观察者实现类)

package observer;

public class Reader2 implements Observer{
	
	private NewsInfo newsInfo;
	
	private Subject subject;
	
	public Reader2(Subject subject){
		this.subject=subject;
		subject.registObserver(this);
	}

	@Override
	public void update(NewsInfo newsInfo) {
		this.newsInfo=newsInfo;
		doReading();
	}
	
	public void doReading(){
		System.out.println("Reader2:"+newsInfo.toString());
	}

	public Subject getSubject() {
		return subject;
	}

	public void setSubject(Subject subject) {
		this.subject = subject;
		subject.registObserver(this);
	}
	
	
}

测试类

package observer;

public class Test {

	public static void main(String[] args) {
		RenMinNewspaper renMinNewspaper=new RenMinNewspaper();
		QianJiangNewspaper qianJiangNewspaper=new QianJiangNewspaper();
		//两个读者关注人民日报
		Reader1 reader1=new Reader1(renMinNewspaper);
		Reader2 reader2=new Reader2(renMinNewspaper);
		
		//人民日报发布新新闻
		renMinNewspaper.setNewsInfo(new NewsInfo("消息1","图片1"));
		renMinNewspaper.setNewsInfo(new NewsInfo("消息2","图片2"));
		
		//读者2取消关注人民日报
		renMinNewspaper.removeObserver(reader2);
		renMinNewspaper.setNewsInfo(new NewsInfo("消息3","图片3"));
		
		//读者2关注钱江日报
		reader2.setSubject(qianJiangNewspaper);
		
		//钱江日报发布新闻
		qianJiangNewspaper.setNewsInfo(new NewsInfo("消息4","图片4"));
		//人民日报发布新闻
		renMinNewspaper.setNewsInfo(new NewsInfo("消息5","图片5"));

	}

}

输出结果


观察者模式中主题不必知道自己的观察者的细节信息,主题只依赖观察者的接口。观察者的增加、删除、修改都不会对主题造成影响。主题只需要把消息推送给所有实现了观察者接口的观察者。这样主题和观察者之间就是松耦合,可以自由的改变、复用主题跟观察者。还是一个因为接口变得很神奇的模式。java内置观察者模式,但是主题是作为超类需要主题实现类去继承,继承自然就会有很多问题。而且自己写一个主题接口也并不难,这里就没有再用java内置的观察者模式。

欢迎批评指正^ ^



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值