观察者模式(Observer)

@@@模式定义:
定义对象间的一种一对多的依赖关系。当一个对象的状态发生改变时,
所有依赖于它的对象都得到通知并被自动更新。
观察者模式又被称为发布——订阅模式。


@@@练习示例: 
订阅报纸


@@@示例代码:
\src\pattern\Subject.java

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

package pattern;

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

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

\src\pattern\Observer.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

package pattern;

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

\src\pattern\NewsPaper.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

package pattern;

/**
 * 报纸对象,具体的目标对象
 */
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();
	}
}

\src\pattern\Reader.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

package pattern;

/**
 * 真正的读者,为了简单就描述一下姓名
 */
public class Reader implements Observer {
    /**
     * 读者的姓名
     */
	private String name;
	
	@Override
	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;
	}
}

\src\user\Client.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

package user;

import pattern.NewsPaper;
import pattern.Reader;

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("本期的内容是观察者模式");
	}
}



[---使用JAVA自带的观察者模式---]


\src\pattern\NewsBook.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

package pattern;

/**
 * 报纸对象,具体的目标实现
 */
public class NewsBook extends java.util.Observable {
    /**
     * 报纸的具体内容
     */
	private String content;
	
	/**
	 * 获取报纸的具体内容
	 * @return 报纸的具体内容
	 */
	public String getContent() {
		return content;
	}
	
	/**
	 * 示意,设置报纸的具体内容,相当于要出版报纸了
	 * @param content 报纸的具体内容
	 */
	public void setContent(String content) {
		this.content = content;
		// 内容有了,说明又出版报纸了,那就通知所有的读者
		// 注意在使用Java中的Observer模式的时候,下面这句话不可少
		this.setChanged();
		// 然后主动通知,这里用的是推的方式
		this.notifyObservers(this.content);
		// 如果用拉的方式,这么调用
		// this.notifyObservers();
	}
}

\src\pattern\BookReader.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

package pattern;

import java.util.Observable;

/**
 * 真正的读者,为了简单就描述一下姓名
 */
public class BookReader implements java.util.Observer {
    /**
     * 读者的姓名
     */
	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	@Override
	public void update(Observable o, Object obj) {
		// 这里采用推的方式
        System.out.println(name + "收到报纸了,阅读它,目标推过来的内容是:" 
        		+ obj);
        
        // 这里获取拉的数据
        System.out.println(name + "收到报纸了,阅读它,主动到目标对象去拉的内容是:"
        		+ ((NewsBook)o).getContent());
	}
}

\src\user\BookClient.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

package user;

import pattern.BookReader;
import pattern.NewsBook;

public class BookClient {
	public static void main(String[] args) {
		// 创建一份报纸,作为被观察者
        NewsBook subject = new NewsBook();
        
        // 创建读者,也就是观察者
        BookReader reader1 = new BookReader();
        reader1.setName("张三");
        
        BookReader reader2 = new BookReader();
        reader2.setName("李四");
        
        BookReader reader3 = new BookReader();
        reader3.setName("王五");
        
        // 注册读者
        subject.addObserver(reader1);
        subject.addObserver(reader2);
        subject.addObserver(reader3);
        
        // 出版报纸
        subject.setContent("本期的内容是观察者模式");
	}

}

@@@模式的实现:
1) 目标和观察者之间一般是一对多,也可以一对一;
2) 观察者可以观察多个目标,一般需要为每个目标定义不同的回调方法而不是在update方法中来区分;
3) 观察者模式有推模型和拉模型两种方式;


@@@模式的优点:
1) 观察者模式实现了观察者和目标对象之间的抽象耦合;
2) 观察者模式实现了动态联动;
3) 观察者模式支持广播通信;


@@@模式的缺点:
1) 可能会引起无谓的操作;


@@@模式的本质:
触发联动


@@@模式体现的设计原则:
NA


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值