观察者模式

B站视频链接:审核中。。。。。。。。

 

观察者模式的定义

        在对象之间定义了一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象会收到通知并自动更新。其实就是发布订阅模式,发布者发布信息,订阅者获取信息,订阅了就能收到信息,没订阅就收不到信息。 

场景

--聊天室程序的创建。服务器创建好后, A,B,C三个客户端连.上来公开聊天。A向服务器发送数据,服务器端聊天数据改变。我们希望将这些聊天数据分别发给其他在线的客户。也就是说,每个客户端需要更新服务器端得数据。
--网站上,很多人订阅了”java主题”的新闻。当有这个主题新闻时,就会将这些新闻发给所有订阅的人。
--大家一起玩CS游戏时,服务器需要将每个人的方位变化发给所有的客户。
上面这些场景,我们都可以使用观察者模式来处理。我们可以把多个订阅者、客户称之为观察者;需要同步给多个订阅者的数据封装到对象中,称之为目标。

核心:消息发布
--观察者模式主要用于1 : N的通知。当一个对象(目标对象Subject或Objservable)的状态变化时,他需要及时告知一系列对象(观察者对象,Observer) ,令他们做出响应。
--通知观察者的方式:消息订阅
●推
--每次都会把通知以广播方式发送给所有观察者,所有观察者只能被动接收。

●拉
--观察者只要知道有情况即可。至于什么时候获取内容,获取什么内容,都可以自主决定。

四个角色

抽象主题角色:也就是一个抽象主题,它把所有对观察者对象的引用保存在一个集合中,每个主题都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。一般用一个抽象类和接口来实现。
抽象观察者角色:为所有的具体观察者定义一个接口,在得到主题通知时更新自己。
具体主题角色:也就是一个具体的主题,在集体主题的内部状态改变时,所有登记过的观察者发出通知。
具体观察者角色:实现抽象观察者角色所需要的更新接口,一边使本身的状态与制图的状态相协调。

 

UML类图

 观察者模式

 

 

举例:实现消息推送给订阅了的观察者,没有订阅的观察者无法收到消息推送。

抽象主题类和观察者抽象接口

package Observer;


/**
 * 定义抽象主题
 * @author 唐磊
 *
 */

public abstract class Subject {
	
	
	abstract void registerObserver(Observer obs);//添加Observer方法
	
	abstract void removeObserver(Observer obs) ;//移除Observer方法

	//通知所有观察者更新状态
	abstract void notifyAllObservers() ;
		
	

}


package Observer;
/**
 * 定义观察者抽象接口
 * @author 唐磊
 *
 */

public interface Observer {
	void update(Subject subject);
}

  具体主题和具体的观察者

package Observer;

import java.util.ArrayList;
/**
 * 定义具体主题类
 * @author 唐磊
 *
 */

public class ConcreteSubject extends Subject{
	private String message;
	//存放观察者的容器
	ArrayList<Observer> list = new ArrayList<Observer>();

	public String getMessage() {
		return message;
	}
	
	//目标对象的状态发生了变化,通知所有的观察者
	public void setMessage(String message) {
		this.message = message;
		System.out.println("QQ推送了更新消息:"+message);
		this.notifyAllObservers();
	}

	@Override
	void registerObserver(Observer obs) {
		list.add(obs);
		
	}

	@Override
	void removeObserver(Observer obs) {
		list.remove(obs);
		
	}

	@Override
	void notifyAllObservers() {
		for (Observer obs : list) {
			obs.update(this);
		}
		
	}
	

}


package Observer;
/**
 * 定义观察者具体类
 * @author 唐磊
 *
 */

public class ConcreteObserver implements Observer{
	private String name;
	private String myMessage;//观察者订阅的目标对象的message
	
	public ConcreteObserver(String name){
		this.name = name;
		
	}

	@Override
	public void update(Subject subject) {
		myMessage = ((ConcreteSubject)subject).getMessage();
		read();
	}
	public void read() {
		System.out.println(name+"收到了推送消息:"+myMessage);
	}

	public String getMyMessage() {
		return myMessage;
	}

	public void setMyMessage(String myMessage) {
		this.myMessage = myMessage;
	}

	
	

}

  Client

package Observer;

public class Client {
	public static void main(String[] args) {
		//目标对象
		ConcreteSubject subject = new ConcreteSubject();
		//创建多个观察者
		ConcreteObserver obs1 = new ConcreteObserver("Lisa");
		ConcreteObserver obs2 = new ConcreteObserver("James");
		ConcreteObserver obs3 = new ConcreteObserver("Mary");
		
		//将这些观察者加入Subject的Observer容器中
		subject.registerObserver(obs1);
		subject.registerObserver(obs2);
		subject.registerObserver(obs3);
		
		//改变subject目标对象的状态,设置推送消息
		subject.setMessage("新冠疫情发布!");
		 
		System.out.println("----------------------------------");
		
		subject.removeObserver(obs1);//Lisa取消了订阅
		System.out.println("Lisa取消了订阅。");
		subject.setMessage("美国新冠确诊人数突破100万人!!!");
		
	
	}

}

  运行结果

观察者模式

 

可以看到lisa取消订阅后,无法收到消息推送。

 

上一篇:Shiro的一些概念解释以及配置了解


下一篇:今天来学习一下MySQl的 临时表,变量,行转列,预处理的一些相关技术的使用!