java中的观察者模式

观察者模式的角色

1、观察者
持有一个方法,接收被观察者的通知
2、被观察者
持有观察者数组、被观察者状态发生变化可以通知观察者

java中利用 java.util.Observablejava.util.Observer就能实现观察者模式
观察者实现Observer的update方法
被观察者继承Observable

Observable

Observable 持有 Observer的数组,Observable的状态改变了就会遍历Observer数组,分别通知Observer对象。

public class Observable {
    private boolean changed = false; // 是否触发状态改变
    private Vector<Observer> obs; // 观察者数组
    public Observable() {
        obs = new Vector<>();
    }
    /** 增加观察者 */
    public synchronized void addObserver(Observer o) {
        if (o == null)
            throw new NullPointerException();
        if (!obs.contains(o)) {
            obs.addElement(o);
        }
    }
    /** 删除观察者 */
    public synchronized void deleteObserver(Observer o) {
        obs.removeElement(o);
    }
    /** 通知观察者状态被触发 */
    public void notifyObservers() {
        notifyObservers(null);
    }
    public void notifyObservers(Object arg) {
        Object[] arrLocal;
        synchronized (this) {
            if (!changed)
                return;
            arrLocal = obs.toArray();
            clearChanged();
        }
        for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);
    }
    public synchronized void deleteObservers() {
        obs.removeAllElements();
    }
    /** 设置状态为被触发 */
    protected synchronized void setChanged() {
        changed = true;
    }
}

Observer

观察者接口

public interface Observer {
    void update(Observable o, Object arg);
}

例子

学生是被观察者,老师和父母是观察者
如果学生在跑步,则通知老师和父母

public class AStudent extends Observable {
	private String name;
	public String getName() {
		return name;
	}
	public AStudent(String name) {
		super();
		this.name = name;
	}
	public void running() {
		String tip = name + " is running...";
		System.out.println(tip);
		this.setChanged();
		this.notifyObservers(tip);
	}
}
public class MParent implements Observer {
	@Override
	public void update(Observable o, Object arg) {
		if(! (o instanceof AStudent)) {
			throw new IllegalArgumentException("只接受AStudent");
		}
		AStudent s = (AStudent)o;
		String string = String.format("MParent正在观察,被观察的人是%s ,描述:%s", s.getName(), arg);
		System.out.println(string);
	}
}
public class MTeacher implements Observer {
	private String name;
	public MTeacher(String name) {
		super();
		this.name = name;
	}
	@Override
	public void update(Observable o, Object arg) {
		// 采用异步 即使该观察者出现异常,不影响其他观察者
		new Thread(()->{
			if(! (o instanceof AStudent)) {
				throw new IllegalArgumentException("只接受MStudent");
			}
			AStudent s = (AStudent)o;
			String string = String.format("%s正在观察,被观察的人是 %s,描述:%s", name, s.getName(), arg);
			System.out.println(string);
			// throw new RuntimeException("1235");
		}).start();
	}
}
public class Demo {
	public static void main(String[] args) {
		AStudent student = new AStudent("小满");
		student.addObserver(new MTeacher("语文老师"));
		student.addObserver(new MTeacher("数学老师"));
		student.addObserver(new MParent());
		student.running();
	}
}
/*
打印结果:
小满 is running...
MParent正在观察,被观察的人是小满 ,描述:小满 is running...
数学老师正在观察,被观察的人是 小满,描述:小满 is running...
语文老师正在观察,被观察的人是 小满,描述:小满 is running...
*/

注意事项

1、避免循环引用
2、如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式

观察者和发布订阅的区别

1、功能相同:都是一个对象发生变化,通知其他对象。
2、不同点:
角色不同:

  • 观察者模式的角色:观察者和被观察者
    被观察者持有观察者数组,代码不完成耦合
  • 发布订阅模式:发布者,订阅者和代理人
    发布者向代理人发布一个主题的消息
    订阅者向代理人订阅一个主题
    发布者和订阅者互不干涉,完全解耦。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_26264237

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值