观察者模式

本篇博客将书写一个简单的观察者模式案例

参考博客:https://blog.csdn.net/qq_33591903/article/details/97005268

什么是观察者模式?

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

被观察者发布信息,观察者收到信息,也可以说是订阅模式,发布者发布信息,订阅者获取信息。

接下来先用一个小案例说明场景,然后用代码实现。

案例场景:

在一个风和日丽,阳光明媚,万里无云,晴空万里(跑题了)的午后,主任躺在自家摇椅上休息打盹,忽然院子里的狗狗叫了一声,主人听到后去看下情况,猫也听到了并且被狗吓的尖叫起来,而由于猫的尖叫,躲在角落的老鼠瑟瑟发抖,然后一溜烟的溜了。主人看到猫被吓到了赶忙回来抱起猫咪安抚一下它的情绪。然后外面的狗子好像不乐意了又叫了一声,主人又去看了看。

 

这里的狗子属于被观察者,

猫既是观察者也是被观察者,猫观察狗,猫被老鼠观察

主人属于观察者,主人观察猫,狗

老鼠属于观察者,老鼠观察猫

 

代码示例

关系如下图

 

  我们将被观察者的职责抽象成Subject,在这个类中,需要保存关注该被观察者的观察者集合,以及增加、删除观察者的方法,以及最重要的通知方法。任何被观察者都需要继承此类,这样只去考虑自己的逻辑方法即可。

/**
 * 
 * @class: Subject
 * @title: 被观察者的职责
 * @desc: 被观察者的职责
 * @author: zhoukaishun
 * @date: 2019年7月24日 上午10:47:51
 * @since: 1.0.0
 */
public class Subject {
	
	private List<Observer> observers = new ArrayList<Observer>();
	
	public void addObserver(Observer o){
		observers.add(o);
	}
	
	public void removeObserver(Observer o){
		observers.remove(o);
	}
	
	public void notifyObservers(){
		observers.forEach(e->{
			e.update(this);
		});
	}
}

将观察者的职责抽象成Observer接口,任何观察者都需要实现此接口。在该接口中,提供update方法,用于在接收到通知后,执行相应的处理方法。

/**
 * 
 * @class: Observer
 * @title: 观察者接口
 * @desc: 观察者接口
 * @author: zhoukaishun
 * @date: 2019年7月24日 上午10:47:27
 * @since: 1.0.0
 */
public interface Observer {
	
	void update(Subject s);

}

实体类

/**
 * 
 * @class: Dog
 * @title: 狗子
 * @desc: 狗仅是被观察者
 * @author: zhoukaishun
 * @date: 2019年7月24日 上午10:45:54
 * @since: 1.0.0
 */
public class Dog extends Subject{
	
	public void bark(){
		System.out.println("狗叫");
		super.notifyObservers();
	}

}
/**
 * 
 * @class: Cat
 * @title: 猫咪
 * @desc: 猫即是被观察者,也是观察者。猫被主人和老鼠观察,猫观察狗
 * @author: zhoukaishun
 * @date: 2019年7月24日 上午10:45:02
 * @since: 1.0.0
 */
public class Cat extends Subject implements Observer{

	@Override
	public void update(Subject s) {
		if(s instanceof Dog){
			System.out.println("猫听到狗叫,吓了一跳,害怕的叫了起来");
			scream();
		}
	}

	private void scream() {
		System.out.println("猫尖叫起来");
		super.notifyObservers();
	}

}
/**
 * 
 * @class: Mouse
 * @title: 老鼠
 * @desc: 老鼠仅是观察者
 * @author: PC
 * @date: 2019年7月24日 上午10:46:28
 * @since: 1.0.0
 */
public class Mouse implements Observer{

	@Override
	public void update(Subject s) {
		if(s instanceof Cat){
			System.out.println("老鼠听到猫叫,吓跑了");
		}
		
	}

}
/**
 * 
 * @class: Person
 * @title: 主人
 * @desc: 主人仅是观察者
 * @author: zhoukaishun
 * @date: 2019年7月24日 上午10:46:53
 * @since: 1.0.0
 */
public class Person implements Observer{

	@Override
	public void update(Subject s) {
		if(s instanceof Dog){
			System.out.println("主人听到狗叫,去看了看");
		}else if(s instanceof Cat){
			System.out.println("主人听到猫叫,去看了看");
		}
		
		
	}

}

测试

public class TestObserver {
	
	public static void main(String[] args) {
		Dog dog = new Dog();
		Cat cat = new Cat();
		Mouse mouse = new Mouse();
		Person person = new Person();
		dog.addObserver(cat);
		dog.addObserver(person);
		cat.addObserver(mouse);
		cat.addObserver(person);
		dog.bark();
		System.out.println("主人看到猫被吓到了,抱起来安抚一下");
		System.out.println("------------相当于猫取消了订阅---------------");
		dog.removeObserver(cat);
		System.out.println("狗又叫了一声");
		dog.bark();
	}
	
}

运行结果

 

说明 

关于抽象类Subject与接口Observer,在java.util包中已经有对应的类。其中这里的Subject(可扩展的被观察者职责类)对应util包下的Observable类,该类提供了线程同步的实现。这里的Observer(观察者接口)对应util包下的Observer接口,两个接口内的方法并没有多大区别。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值