什么是观察者模式

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

我们可以举个例子,比如报纸或者杂志的订阅,我们读者属于订阅者,报纸或者杂志属于出版者,那么:

  1. 向某家报纸社订阅报纸,只要他们有新报纸出版,就会给读者送过去,只要你是他的订阅者,那么你就一直会收到新报纸。
  2. 当你不想再看报纸的时候,取消订阅,他们就不会再送新报纸过来了。
  3. 只要报纸社还在运营,就会一直有人向他们订阅报纸或者取消订阅报纸。

以上就是一个典型的适用于观察者模式的案例,我们画个图说明一下:
在这里插入图片描述
对于这种一对多的关系,我们常用 Subject 和 Observer 接口的类设计来进行实现:
在这里插入图片描述

  • Subject:这是主题接口,对象使用此接口注册为观察者,或者自己从观察者中删除
  • Observer:所有潜在的观察者都必须实现观察者接口,这个接口只有 update() 一个方法,当主题状态改变时它被调用
  • ConcreteSubject:一个具体主题总是实现主题接口,除了注册和撤销方法之外,具体主题还实现了 notifyObserver() 方法,此方法用于在改变状态时更新所有当前的观察者
  • ConcreteObserver:具体的观察者可以是实现此接口的任意类,观察者必须注册具体主题,以便接收更新

  观察者模式提供一种对象设计,让主题和观察者之间松耦合。我们可以在代码中随时实现一个实现了 Observer 接口的新观察者,运行时也可以使用新观察者取代现有的观察者,主题不会收到任何的影响,同样可以在任何时候删除某些观察者。

下面我们以微信公众号为例子,假设微信用户就是观察者,微信公众号是发布者,有多个用户关注了 NBA 这个公众号,当这个公众号更新时就会通知这些订阅者。

先抽象一个观察者:

public interface Observer{
	public void update(String message);
}

然后定义一个具体的观察者实现观察者接口,这个接口实现了更新的方法:

public class VXUser implements Observer{
	private String vxName;

	public VXUser(String vxName){
		this.vxName = vxName;
	}

	@Override
	public void update(String message){
		System.out.println(name + ",您专注的" + message);
	}
}

有了观察者之后,我们再定义发布者,也就是微信公众号:

public interface Subject{

	//增加订阅者
	public void registerObserver(Observer observer);

	//删除订阅者
	public void  removeObserver(Observer observer);

	//更新消息时通知订阅者
	public void notify(String message);
}

同上我们再定义一个具体的发布者类——微信公共号,内部维护了一个订阅该公众号的 list,并实现了接口中的方法:

public class VXSubscriptionSubject implements Subject{
	//存储订阅公众号的微信用户
	private List<Observer> vxUserList = new ArrayList<>();

	@Override
	public void registerObserver(Observer observer){
		vxUserList.add(observer);
	}

	@Override
	public void removeObserver(Observer observer){
		vxUserList.remove(observer);
	}

	@Override
	public void notify(String message){
		for(Observer ob : vxUserList){
			observer.update(message);
		}
	}
}

以上就完成了整个观察者模式的基本功能,我们可以写一个客户端程序试一下:

public class Client{
	public static void main(String[] args){
		VXSubscriptionSubject vxSub = new VXSubscriptionSubject();
		//创建一个微信用户
		VXUser user1 = new VXUser("user1");
		VXUser user2 = new VXUser("user2");
		VXUser user3 = new VXUser("user3");

		//订阅整个公众号
		vxSub.registerObserver(user1);
		vxSub.registerObserver(user2);
		vxSub.registerObserver(user3);

		//公共号发布新消息
		vxSub.notify("NBA专栏更新啦");
	}
}

运行后输出的结果如下:

user1,您关注的NBA专栏更新啦
user2,您关注的NBA专栏更新啦
user3,您关注的NBA专栏更新啦

  综上我们可以看到,观察者模式的实现接触了耦合,让双方都依赖于抽象,从而使得各自的变换都不会影响到另一方。但是在应用的时候需要考虑一下开发效率和运行效率的问题,程序中包含一个发布者,多个观察者,开发、调试等内容会比较复杂,而且在 Java 中消息的通知一般是顺序执行,那么一个观察者卡顿了,会影响整体的执行效率,在这种情况下需要使用异步实现。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

suppppper

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

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

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

打赏作者

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

抵扣说明:

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

余额充值