• 设计模式13---设计模式之观察者模式(Observer)(行为型)


    1.场景模式抽象

    订阅报纸的过程,如果报纸来了的时间不确定,那么订报纸的人如何知道呢?可以抽象为:当一个对象的状态发生改变的时候,如何让依赖他的所有对象得到通知,并进行相应的处理呢?生活中最常见的例子就是:当你一上线,QQ后台就给你不上线的时候收到的所有的消息。

    2.使用观察者模式来解决方案

    2.1观察者模式定义

    定义对象间的一种一对多的依赖关系。当一个对象的状态发生改变的时候,所有依赖他的对象都得到通知并进行自动更新。

    2.2观察者模式结构说明

     

    2.3.观察者模式示例代码

    package demo11.observer.example1;
    
    
    import java.util.*;
    /**
     * 目标对象,它知道观察它的观察者,并提供注册和删除观察者的接口
     */
    public class Subject {
    	/**
    	 * 用来保存注册的观察者对象
    	 */
    	private List<Observer> observers = new ArrayList<Observer>();
    	/**
    	 * 注册观察者对象
    	 * @param observer 观察者对象
    	 */
    	public void attach(Observer observer) {
    		observers.add(observer);
    	}
    	/**
    	 * 删除观察者对象
    	 * @param observer 观察者对象
    	 */
    	public void detach(Observer observer) {
    		observers.remove(observer);
    	}
    	/**
    	 * 通知所有注册的观察者对象
    	 */
    	protected void notifyObservers() {
    		for(Observer observer : observers){
    			observer.update(this);
    		}
    	}
    }
    ***************************************************************************************************
    package demo11.observer.example1;
    
    
    /**
     * 具体的目标对象,负责把有关状态存入到相应的观察者对象,
     * 并在自己状态发生改变时,通知各个观察者
     */
    public class ConcreteSubject extends Subject {
    	/**
    	 * 示意,目标对象的状态
    	 */
    	private String subjectState;
    	public String getSubjectState() {
    		return subjectState;
    	}
    	public void setSubjectState(String subjectState) {
    		this.subjectState = subjectState;
    		//状态发生了改变,通知各个观察者
    		this.notifyObservers();
    	}
    }
    ***************************************************************************************************
    package demo11.observer.example1;
    
    
    /**
     * 观察者接口,定义一个更新的接口给那些在目标发生改变的时候被通知的对象
     */
    public interface Observer {
    	/**
    	 * 更新的接口
    	 * @param subject 传入目标对象,好获取相应的目标对象的状态
    	 */
    	public void update(Subject subject);
    
    
    }
    ***************************************************************************************************
    package demo11.observer.example1;
    
    
    /**
     * 具体观察者对象,实现更新的方法,使自身的状态和目标的状态保持一致
     */
    public class ConcreteObserver implements Observer {
    	/**
    	 * 示意,观者者的状态
    	 */
    	private String observerState;
    	
    	public void update(Subject subject) {
    		// 具体的更新实现
    		//这里可能需要更新观察者的状态,使其与目标的状态保持一致
    		observerState = ((ConcreteSubject)subject).getSubjectState();
    	}
    }

    3.使用观察者模式来实现示例

    3.1目标对象,作为被观察者

    package demo11.observer.example2;
    
    
    import java.util.ArrayList;
    import java.util.List;
    
    
    /**
     * 目标对象,作为被观察者
     */
    public class Subject {
    	/**
    	 * 用来保存注册的观察者对象,也就是报纸的订阅者
    	 */
    	private List<Observer> readers = new ArrayList<Observer>();
    	/**
    	 * 报纸的读者需要先向报社订阅,先要注册
    	 * @param reader 报纸的读者 
    	 * @return 是否注册成功
    	 */
    	public void attach(Observer reader) {
    		readers.add(reader);
    	}
    	/**
    	 * 报纸的读者可以取消订阅
    	 * @param reader 报纸的读者
    	 * @return 是否取消成功
    	 */
    	public void detach(Observer reader) {
    		readers.remove(reader);
    	}
    	/**
    	 * 当每期报纸印刷出来后,就要迅速的主动的被送到读者的手中,
    	 * 相当于通知读者,让他们知道
    	 */
    	protected void notifyObservers() {
    		for(Observer reader : readers){
    			reader.update(this);
    		}
    	}
    }

    3.2报纸对象,具体的目标实现

    package demo11.observer.example2;
    /**
     * 报纸对象,具体的目标实现
     */
    public class NewsPaper extends Subject {
    	/**
    	 * 报纸的具体内容
    	 */
    	private String content;
    
    
    	/**
    	 * 获取报纸的具体内容
    	 * 
    	 * @return 报纸的具体内容
    	 */
    	public String getContent() {
    		return content;
    	}
    
    
    	/**
    	 * 示意,设置报纸的具体内容,相当于要出版报纸了
    	 * 
    	 * @param content
    	 *        报纸的具体内容
    	 */
    	public void setContent(String content) {
    		this.content = content;
    		// 内容有了,说明又出报纸了,那就通知所有的读者
    		notifyObservers();
    	}
    }

    3.3观察者,比如报纸的读者

    package demo11.observer.example2;
    /**
     * 观察者,比如报纸的读者
     */
    public interface Observer {
    	/**
    	 * 被通知的方法
    	 * @param subject 具体的目标对象,可以获取报纸的内容
    	 */
    	public void update(Subject subject);
    }

    3.4真正的读者,为了简单就描述一下姓名

    package demo11.observer.example2;
    /**
     * 真正的读者,为了简单就描述一下姓名
     */
    public class Reader implements Observer{
    	/**
    	 * 读者的姓名
    	 */
    	private String name;
    
    
    	public void update(Subject subject) {
    		//这是采用拉的方式
    		System.out.println(name+"收到报纸了,阅读先。内容是==="+((NewsPaper)subject).getContent());
    	}
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    }

    3.5客户端使用

    package demo11.observer.example2;
    
    
    public class Client {
    	public static void main(String[] args) {
    		//创建一个报纸,作为被观察者
    		NewsPaper subject = new NewsPaper();
    		
    		//创建阅读者,也就是观察者
    		Reader reader1 = new Reader();
    		reader1.setName("张三");
    		
    		Reader reader2 = new Reader();
    		reader2.setName("李四");
    		
    		Reader reader3 = new Reader();
    		reader3.setName("王五");
    		
    		//注册阅读者
    		subject.attach(reader1);
    		subject.attach(reader2);
    		subject.attach(reader3);
    		
    		//要出报纸啦
    		subject.setContent("本期内容是观察者模式");
    	}
    }

    4.认识观察者模式

    4.1目标和观察者之间的关系

    典型的一对多的关系。

    4.2单向依赖

    观察者依赖目标,目标不依赖观察者。

    4.3观察者模式的调用顺序图

     

    4.4推模型

    推模型:顾名思义,目标对象主动向观察者推送消息,不管观察者是否需要,相当于广播通信
    与前面不同的地方在于

    	public void update(String content) {
    		//这是采用推的方式
    		System.out.println(name+"收到报纸了,阅读先。内容是==="+content);
    	}
    
    
    	/**
    	 * 当每期报纸印刷出来后,就要迅速的主动的被送到读者的手中,
    	 * 相当于通知读者,让他们知道
    	 * @param content 要主动推送的内容
    	 */
    	protected void notifyObservers(String content) {
    		for(Observer reader : readers){
    			reader.update(content);
    		}
    	}
    
    
    	/**
    	 * 示意,设置报纸的具体内容,相当于要出版报纸了
    	 * @param content 报纸的具体内容
    	 */
    	public void setContent(String content) {
    		this.content = content;
    		//内容有了,说明又出报纸了,那就通知所有的读者
    		notifyObservers(content);
    	}

    4.5拉模型

    拉模型:顾名思义,目标对象在通知观察者的时候,只传递少量信息,如果观察者需要更具体的信息,由观察者主动到目标对象去获取。

    	public void update(Subject subject) {
    		// 这是采用拉的方式
    		System.out.println(name + "收到报纸了,阅读先。内容是===" + ((NewsPaper) subject).getContent());
    	}

    4.6java中的观察者模式

    java中已经定义了观察者模式,详细的可以查查。这里不再复述。基本上差不多。

    5.观察者模式思考

    5.1优缺点:

    优点:实现了观察者和目标之间的抽象耦合,实现了动态联动,支持广播通信
    缺点:可能会引起无谓的操作

    5.2观察者模式的本质:

    触发联动

  • 相关阅读:
    struts2校验器
    Struts2 验证框架 validation.xml 常用的验证规则
    MVC 无法找到资源
    架构设计
    金山西山居初赛第二场 美素数
    K Smallest Sums
    金山游戏编程复赛 连续最大积
    C++大作业之链表实现的高精度加法,减法,和数组实现的高精度乘法。
    POJ 3250 Bad Hair Day
    PoJ2492A Bug's Life并查集
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3221535.html
Copyright © 2020-2023  润新知