[设计模式] 观察者模式

定义

观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象状态改变时,他的所有的依赖者都会收到通知并自动更新。

使用场景

观察者模式是典型的发布——订阅模式,通过两个对象间的松耦合方式结合,经常用于解耦。
在观察者模式中,主题对象(Subject)和观察者对象(Observer)之间是一对多的关系,当主题对象的状态之间有变化,观察者就会被通知,从而完成更新。
观察者模式经常用于GUI系统,如Android中的ListView。

UML类图

其UML类图如下:
这里写图片描述

示例

中秋节快要来了,其中某地的学校、工厂、医院都在等政府的放假通知,当政府发出通知后,这几个单位将同时得到通知内容。这时我们可以通过观察者模式来实现,其中政府是一个主题对象,而学校、医院、工厂是观察者:

  • Step1.首先定义主题接口和观察者接口:
public interface Subject {

	void registObserver(Observer o);
	void unregistObserver(Observer o);
	void notifyChanged(String str);
}

public interface Observer {

	void onChanged(String str);
}

  • Step2.定义具体的主题类和观察者类:
package com.jyq.observer;

import java.util.ArrayList;

public class Government implements Subject {

	//用来存储观察者
	private ArrayList<Observer> observers = new ArrayList<>();
	
	//注册一个观察者
	@Override
	public void registObserver(Observer o) {
		// TODO Auto-generated method stub
		if (observers.indexOf(o) < 0) {
			observers.add(o);
		}
	}
	
	//取消注册观察者
	@Override
	public void unregistObserver(Observer o) {
		// TODO Auto-generated method stub
		int i = observers.indexOf(o);
		if (i >= 0) {
			observers.remove(i);
		}
	}

	//通知所有观察者
	@Override
	public void notifyChanged(String str) {
		// TODO Auto-generated method stub
		for(int i=0; i<observers.size();i++) {
			observers.get(i).onChanged(str);
		}
	}
}

public class School implements Observer {

	public School(Subject subject) {
		subject.registObserver(this);
	}
	
	@Override
	public void onChanged(String str) {
		// TODO Auto-generated method stub
		System.out.println("School:"+str);
	}
}


public class Hospital implements Observer {

	public Hospital(Subject subject) {
		subject.registObserver(this);
	}
	
	@Override
	public void onChanged(String str) {
		// TODO Auto-generated method stub
		System.out.println("Hospital:"+str);
	}

}


public class Factory implements Observer {

	public Factory(Subject subject) {
		subject.registObserver(this);
	}
	
	@Override
	public void onChanged(String str) {
		// TODO Auto-generated method stub
		System.out.println("Factory:"+str);
	}

}
  • Step3.主题对象状态发生改变,于是通知观察者:
public class DemoObserverDesign {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Government government = new Government();
		School higSchool = new School(government);
		Hospital hospital = new Hospital(government);
		Factory factory = new Factory(government);
		government.notifyChanged("今年中秋,放假10天!");
	}
}

运行程序,输出结果如下:

School:今年中秋,放假10天!
Hospital:今年中秋,放假10天!
Factory:今年中秋,放假10天!

总结

  • 1.观察者模式定了对象间一对多的关系,一个主题对应多个观察者;
  • 2.在观察者模式中,主题和观察者都使用接口,针对接口编程,而非针对实现编程;
  • 3.观察者和主题对象通过松耦合实现,主题对象唯一知道关于观察者对象的就是其实现了观察者接口;
  • 4.观察者模式中,利用组合将观察者对象组合进了主题中。

关于java内置的观察者模式

从JDK1.0开始,java中就内置了观察者模式:

import java.util.Observable;
import java.util.Observer;

其中java.util.Observable是主题对象的基类,如果要通过java内置API实现观察者模式,则主题对象需要继承Observable类。java.util.Observer则是观察者接口,所有的观察者需要实现该接口,如果将示例通过java内置API来实现,则类结构如下:

import java.util.ArrayList;
import java.util.Observable;

public class Government extends Observable {

	public void sendMsg() {
		setChanged();
		//通知所有观察者
		notifyObservers();
	}
}

import java.util.Observable;
import java.util.Observer;

public class School implements Observer {

	public School(Observable observerable) {
		observerable.addObserver(this);
	}
	@Override
	public void update(Observable o, Object arg) {
		// TODO Auto-generated method stub
		System.out.println("School:");
	}

}

然而这个API并不常用,原因在于若使用该API,则主题对象必须继承java.util.Observable,因此就限制了主题类的复用能力。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值