设计模式之观察者模式
内容抄自《设计模式》清华大学出版社,2011
模式动机:
无论是在现实世界中还是在软件系统中,人们常常会遇到这样一类问题,一个对象的状态改变会引发其他对象的
状态改变,如十字路口的交通信号灯,红灯亮则汽车停,绿灯亮则汽车行,这些对象之间存在一种依赖关系,一个
对象的行为会导致依赖它的其他对象发生反应。
模式定义:
定义对象间的一种一对多的依赖关系,使得每当一个对象的状态发生改变时,其相关依赖对象都得到通知并被自动
更新。观察者模式又叫发布订阅模式。
结构分析:
包含角色:
1.Subject(抽象观察目标)
2.ConcreteSubject(具体观察目标)
3.Observer(抽象观察者)
4.ConcreteObserver(具体观察者) //如果和具体观察目标存在关联关系,则比较复杂
模式分析:
public abstract class Subject{
protected ArrayList observers = new ArrayList<>();
public abstract void add(Observer observer);
public abstract void remove(Observer observer);
public abstract void notify();
}
public class ConcreteSubject extends Subject{
@Override
public void add(Observer observer){
observers.add(observer);
}
@Override
public void remove(Observer observer){
observers.remove(observer);
}
@Override
public void notify(Observer observer){
for(Observer o:observers){
o.accept();
}
}
}
public interface Observer{
public void accept();
}
public class ConcreteObserver{
@Override
public void accept(){
//dosome
}
}
优点:
1.使观察者和观察目标解耦,观察目标不需要了解具体观察者。
2.支持广播通信,简化了一对多系统设计的难度。
3.符合开闭原则,新增具体观察者和观察目标,无须修改现有代码。
缺点:
1.如果在观察者和观察目标之间有循环依赖的话,可能会发生循环调用。
2.观察者不知道观察目标发生了什么样的变化,只知道发生了变化。
3.观察者被通知的动作都一样,需要使用事件委托机制解决
适用环境:
1.一个抽象模型有两个方面,一个方面多的改变会使得另一方面的改变。将这些方面封装在独立的对象中,使他们可以各自独立的改变和复用
2.一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变。
3.需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象。。。。。可以使用观察者模式创建一种链式触发机制
Java自带观察者模式分析:
包含角色:
1.Subject(抽象观察目标->java.util.Observable)
2.ConcreteSubject(具体观察目标->X extends Observable)
3.Observer(抽象观察者->Observer)
4.ConcreteObserver(具体观察者->X implements Observer)
public ConcreteSubject extends Observable{
public void dosome(){
super.setChanged();
super.notifyObservers();
}
}
public ConcreteObserver implements Observer{
@Override
public void update(Observable o, Object arg) {
//o 为具体观察目标本身
//dosome
}
}
栗子:java自带
class Example {
static class MyObservable extends Observable{
public void dodo() {
super.setChanged();
super.notifyObservers("aa");
}
}
static class MyOb implements Observer{
@Override
public void update(Observable o, Object arg) {
System.out.println(o);
System.out.println(arg);
}
}
public static void main(String[] args) {
MyObservable observable = new MyObservable();
observable.addObserver(new MyOb());
observable.dodo();
}
}
栗子:自写
public class Test {
static interface Observer{
public void accept();
}
static class Observer1 implements Observer{
@Override
public void accept() {
System.out.println("观察者1收到通知");
}
}
static class Observer2 implements Observer{
@Override
public void accept() {
System.out.println("观察者2收到通知");
}
}
//被观察者
static class Obserable{
private List<Observer> obList;
public Obserable() {
this.obList = new ArrayList<>();
}
public void addObserver(Observer ob){
obList.add(ob);
}
public void removeObserver(Observer ob){
obList.remove(ob);
}
public void doSome(){
for (Observer observer : obList) {
observer.accept();
}
}
}
public static void main(String[] args) {
Obserable obserable = new Obserable();
//obserable.addObserver( new Observer1());
//obserable.addObserver( new Observer2());
obserable.doSome();
}
}
栗子:事件委托
/**
* 为了解决各观察者行为不一致的问题
*/
public class ObWithEvent {
static class EventManager{
private List<Event> list = new ArrayList<>();
public void add(Event e){
list.add(e);
}
public void remove(Event e){
list.remove(e);
}
public void publish() {
for (Event event : list) {
event.invoke();
}
}
}
static abstract class Publisher{
protected EventManager manager = new EventManager();
public void add(Event e){
this.manager.add(e);
}
public void remove(Event e){
this.manager.remove(e);
}
public void publish(){
this.manager.publish();
}
}
static class ConcretePublisher extends Publisher{
}
//把各种信息封装成Event
static class Event{
private Object obj;
private String methodName;
public Event(Object obj, String methodName) {
this.obj = obj;
this.methodName = methodName;
}
public void invoke(){
try {
Method method = obj.getClass().getDeclaredMethod(methodName,new Class<?>[0]);
method.invoke(obj, null);
} catch (Exception e) {
e.printStackTrace();
}
}
}
//具体观察者 (没有抽象了)
static class LoginListener{
public void handler2() {
System.out.println("Login开始处理");
}
}
//具体观察者 (没有抽象了)
static class OtherListener{
public void handler1() {
System.out.println("Other开始处理");
}
}
public static void main(String[] args) {
LoginListener aa = new LoginListener();
OtherListener bb = new OtherListener();
ConcretePublisher publisher = new ConcretePublisher();
publisher.add(new Event(aa,"handler2"));
publisher.add(new Event(bb,"handler1"));
publisher.publish();
}
}