zoukankan      html  css  js  c++  java
  • 行为型模式之Observer模式

    观察者模式(又被称为发布-订阅模式、模型-视图模式、源-收听者模式或从属者模式)

    观察者模式中,一个目标对象管理所有依赖于它的观察者对象,并且在它本身的状态改变时主动发出通知。

    应用场景

    拍卖会可以认为是观察者模式的一种,每个投标人都可以出价。拍卖师开始拍卖时,他观察是否有牌子举起出价。每次接受一个新的出价都改变了拍卖的当前价格,并且广播给所有的投标人。

    在JDK中的应用

    • java.util.EventListener
    • javax.servlet.http.HttpSessionBindingListener
    • javax.servlet.http.HttpSessionAttributeListener
    • javax.faces.event.PhaseListener

    参与角色

    抽象主题(Subject):

    抽象主题提供一个接口,可以增加和删除观察者对象;
    Subject把所有观察者对象的引用保存到一个集合里,每个主题都可以有任何数量的观察者;

    具体主题(ConcreteSubject):
    存储有关状态,这些状态应与目标的状态保持一致;
    将有关状态存入具体观察者对象;
    在具体主题内部状态改变时,给所有登记过的观察者发出通知;
    实现Observer的更新接口以使自身状态与目标的状态保持一致。

    抽象观察者(Observer):
    为所有的具体观察者定义一个接口,在得到主题通知时更新自己。

    具体观察者(ConcreteObserver):
    实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态协调。

    观察者模式的类图

    观察者模式的意图是定义对象之间一对多的依赖关系,一个对象状态改变,其他相关联的对象就会得到通知并被自动更新。

    观察者模式实例

    在这个实例中,观察者能够注册此主题,任何在此主题上的内容提交导致的变化都会通知所有在注册的观察者。

    Subject抽象主题:

    public interface Subject {
    	//注册观察者
    	public void attach(Observer obs);
    	//移除观察者
    	public void detach(Observer obs);
    	
    	//通知观察者
    	public void noticeObservers();
    	//获得主题的更新信息
    	public String getUpdate();
    	
    }
    

      

    Observer抽象订阅者:

    public interface Observer {
    
    	/**
    	 * 获取主题变化,由Observer触发
    	 */
    	public void update();
    	
    	/**设置主题对象*/
    	public void setSubject(Subject sbj);
    }
    

      

    ConcreteSubject具体主题:

    public class ConcreteSubject implements Subject{
    
    	private String message;//传递的消息体
    	private boolean changed;//消息状态标识
    	//存储注册的观察者集合
    	private List<Observer> observers;
    	
    	public ConcreteSubject(){
    		this.observers=new ArrayList<Observer>();
    	}
    	
    	/**
    	 * 这里的Subject可以是主题订阅,具体关系中的老师-学生等
    	 */
    	@Override
    	public void attach(Observer obs) {	
    		if(obs==null)
    			throw new NullPointerException("Null Observer");
    		if(!observers.contains(obs))
    			observers.add(obs);
    	}
    
    	@Override
    	public void detach(Observer obs) {
    		observers.remove(obs);
    	}
    
    	@Override
    	public void noticeObservers() {
    		List<Observer> temp=null;
    		/**
    		 * 防止观察者收到订阅以前由被观察者发出的消息
    		 */
    		synchronized (ConcreteSubject.class) {
    			if(!changed)
    				return;
    			temp=new ArrayList<>(this.observers);
    			this.changed=false;
    		}
    		
    		for(Observer obs:temp){
    			/**调用观察者的方法*/
    			obs.update();
    		}
    	}
    
    	@Override
    	public String getUpdate() {
    		return this.message;
    	}
    	
    	public void postMessage(String msg){
    		this.message=msg;
    		this.changed=true;
    		//通知到观察者
    		noticeObservers();
    	}
    
    }
    

      

    ConcreteObserver具体观察者:

    public class ConcreteObserver implements Observer{
    	
    	//此处用于标注不同的观察者
    	private String name;
    	//消息结果字段
    	private String result;
    	//设置主题
    	private Subject subject;
    	
    	public ConcreteObserver(String name){
    		this.name=name;
    	}
    
    	@Override
    	public void update() {
    		/**从主题那里取得消息更新*/
    		result=subject.getUpdate();
    		/**处理消息*/
    		System.out.println(name+" get message "+result);
    	}
    
    	//设置主题
    	@Override
    	public void setSubject(Subject sbj) {
    		this.subject=sbj;
    	}
    
    }
    

    发布-订阅实例:

    public class OBClient {
    
    	public static void main(String[] args){
    		ConcreteSubject sbj=new ConcreteSubject();
    	
    		ConcreteObserver obs1=new ConcreteObserver("obs1");
    		ConcreteObserver obs2=new ConcreteObserver("obs2");
    		ConcreteObserver obs3=new ConcreteObserver("obs3");
    		
    		/**注册到主题*/
    		sbj.attach(obs1);
    		sbj.attach(obs2);
    		sbj.attach(obs3);
    		
    		/**设置被观察对象*/
    		obs1.setSubject(sbj);
    		obs2.setSubject(sbj);
    		obs3.setSubject(sbj);
    		
    		/**发送消息*/
    		sbj.postMessage("hello world!");
    
    	}
    	
    }
    

    测试结果:

    参考:

    JAVA中的观察者模式实例教程

    观察者模式(Observer)解析例子

    维基百科·观察者模式

  • 相关阅读:
    【新阁教育】能不能让你的电脑变成一台PLC?
    【新阁教育】针对零基础小白的SQL2012安装攻略完整版
    【新阁教育】穷学上位机系列——搭建STEP7仿真环境
    【新阁教育】做了这么久,才知道什么是上位机
    【新阁教育】S7.NET+Log4Net+SQLSugar+MySQL搭建Iot平台
    【新阁教育】基于ModbusTCP实现西门子1200PLC定位控制案例
    C#数据结构-二叉树-链式存储结构
    C#数据结构-二叉树-顺序存储结构
    DataTable 将一列转为List
    字符串匹配—KMP算法
  • 原文地址:https://www.cnblogs.com/binyue/p/3728485.html
Copyright © 2011-2022 走看看