【设计模式】观察者模式

From: https://liudongdong1.github.io/

察者模式又被称为发布订阅(Publish/Subscribe)模式,属于对象行为型模式。它定义对象间的一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,当主题对象状态发生改变时,它的所有观察者都会收到通知并自动更新相关内容。主题是通知的发布者,它发出通知时并不需要知道谁是它的观察者,可以有任意数目的观察者订阅并接收通知.

核心类说明:

  • Subject:抽象主题,即被观察对象,本身维护一个观察者集合。
  • Observer:抽象观察者,根据主题状态变化做出相应反应,本身维护一个主题的引用。

注意事项:

  • Java 中已经有了对观察者模式的支持类。
  • 避免循环引用。
  • 如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。
.1. 自定义观察者

//定义主题
public interface Subject {
    void registerObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObserver();
}
public class Blog implements Subject{
 	//存储已定阅的读者
	private ArrayList observerList;
	//这是更新的文章
	private String news;
	
	public Blog(){
		observerList = new ArrayList();
	}
	@Override
	public void registerObserver(Observer observer){
		observerList.add(observer);
	}
	@Override
    public void removeObserver(Observer observer){
    	int index = observerList.indexOf(observer);
    	//不要忘记如果observer没有订阅的话会返回-1
    	if(index>=0){
    		observerList.remove(index);
    	}
    }
    @Override
    public void notifyObserver(Object arg){
    	 for(int i=0;i<observerList.size();i++){
            Observer observer = (Observer)observerList.get(i);
            observer.update(this,arg);
        }
    }
    //文章更新时进行
    public void newsChanged(){
    	notifyObserver(this.news);
    }
	//模拟博客更新文章
	public void setNews(){
		news = "观察者模式";
		notifyObserver();
	}
    
}
//观察者
public interface Observer {
	//因为一个观察者可能订阅了多个主题,所以需要确定是哪个主题
    void update(Subject subject,Object arg);
}
public class Reader implements Observer{
	private String news;
    //存储主题,以方便之后的退订操作
    private Subject subject;
    public Reader(Subject subject){
        this.subject = subject;
        //读者订阅
        subject.registerObserver(this);
    }

    @Override
    public void update(Subject subject, Object arg) {
    //确定主题身份
        if(subject instanceof Blog){
            news = (String)arg;
        }
        //读者阅读博客
        read(this.news);
    }
	//该方法模拟读者阅读
    public void read(String news){
        System.out.println(news);
    }
    //退订
    public removeSubscript(){
    	this.subject.removeObserver(this);
    }
}
public static void main(String[] args) {
        Blog blog = new Blog();
        //读者订阅博客
        Reader reader = new Reader(blog);
        //博客更新
        blog.setNews();
}
.2. java自带类

public class NewspaperOffice extends Observable {
    private String news; // 报社新闻内容

    //注意与自己实现的不同处,添加观察者放在超类中处理
    public NewspaperOffice() {}

    public void setNews(String news) {
        this.news = news;
        newsChanged();
    }
    public String getNews() {
        return news;
    }
    // 内容改变时,通知观察者
    public void newsChanged() {
        setChanged();
        notifyObservers(); 
    }
}
public class Eric implements Observer {
    private Observable observable;  // 主题的引用
    private String news;
    
    public Eric(Observable observable){
        this.observable = observable;
        this.observable.addObserver(this); // 把此对象添加为观察者
    }

    @Override
    public void update(Observable o, Object arg) {
        if (o instanceof NewspaperOffice) {
            NewspaperOffice newspaperOffice = (NewspaperOffice) o;
            this.news = newspaperOffice.getNews();
            showNews(); //更新信息后显示信息
        }
    }

    public void showNews(){
        System.out.println("Eric: "+news);
    }
}
public class Shealtiel implements Observer {
    private Observable observable; //主题的引用
    private String news;

    public Shealtiel(Observable observable){
        this.observable = observable;
        this.observable.addObserver(this); //把此对象添加为观察者
    }

    @Override
    public void update(Observable o, Object arg) {
        if (o instanceof NewspaperOffice) {
            NewspaperOffice newspaperOffice = (NewspaperOffice) o;
            this.news = newspaperOffice.getNews();
            showNews(); //更新信息后显示信息
        }
    }

    public void showNews(){
        System.out.println("Shealtiel: "+news);
    }
}
public class Demo {
    public static void main(String[] args) {
        //实例化报社类(被观察者)
        NewspaperOffice newspaperOffice = new NewspaperOffice();
        //实例化订阅者类(观察者)
        Eric eric = new Eric(newspaperOffice);
        Shealtiel shealtiel = new Shealtiel(newspaperOffice);

        //报社更新信息,自动会通知相应的观察者
        System.out.println("报社更新第一条信息,注意观察者接受的信息:");
        newspaperOffice.setNews("This is the first news!");
        System.out.println("
报社更新第二条信息,注意观察者接受的信息:");
        newspaperOffice.setNews("This is the second news!");

        //eric对象取消订阅报纸新闻,则此后的新闻信息将不会通知eric
        System.out.println("
Eric取消订阅新闻信息");
        newspaperOffice.deleteObserver(eric);

        System.out.println("报社更新第三条信息,注意此时观察者数量:");
        newspaperOffice.setNews("This is the third news!");
    }
}
原文地址:https://www.cnblogs.com/liu-dongdong/p/15117646.html