模式概述:
允许你定义一种订阅机制, 可在对象事件发生时通知多个 “观察” 该对象的其他对象。
使用场景:
- 当一个对象状态的改变需要改变其他对象, 或实际对象是事先未知的或动态变化的时, 可使用观察者模式。
- 当应用中的一些对象必须观察其他对象时, 可使用该模式。 但仅能在有限时间内或特定情况下使用。
代码样例:
代码背景: 张三、李四、王五都想买最新版的华为手机,每天都跑到华为营业厅看是否上架,如果未上架,他们都要空手而归;换种思路,营业厅可以向所有顾客发送邮件,这样,部门顾客就无须前往营业厅了,但是会引起没有需求的用户的投诉(打扰垃圾邮件);陷入了一个矛盾,要么浪费顾客时间去营业厅查看最新手机是否上架,要么浪费资源通知非目标用户。解决方案是使用观察者,营业厅是发布者,关注营业厅手机上架信息的顾客(张三、李四、王五)为订阅者(观察者);当营业厅新手机上架时给订阅的所有订阅者发送邮件,当然发布者提供订阅机制,每个订阅者都能订阅和取消订阅。以下代码是以华为营业厅上架最新手机和手机售罄两个事件来通知所有观察者的观察者设计模式代码样例:
/**
* 商店基类(被观察者)
*/
public abstract class Store {
List<Observer> observers = new ArrayList<>();
//发布接口(事件发生后通知观察者进行业务处理)
public abstract void notify(Event event);
//注册观察者
public void subscribe(Observer observer){
observers.add(observer);
}
//解除观察者
public void unSubscribe(Observer observer){
observers.remove(observer);
}
}
/**
* 华为手机商店(具体的被观察者)
*/
public class HuaWeiStore extends Store{
private String name;
public HuaWeiStore(String name){
this.name = name;
}
public String getName() {
return name;
}
@Override
public void notify(Event event) {
for (Observer observer:this.observers){
observer.update(event);
}
}
/**
* 新产品上架
*/
public void newProductUp(){
UpEvent event = new UpEvent(new Date(),this);
this.notify(event);
}
/**
* 产品售罄
*/
public void cellOut(){
CellEvent event = new CellEvent(new Date(),this);
this.notify(event);
}
}
/**
* 事件基类,被观察者发生动作封装成事件
*/
public abstract class Event<T> {
//获取事件发生的对象(被观察者),多数情况下,处理事件,需要事件源信息
public abstract T getSource();
}
/**
* 新产品上架事件
*/
public class UpEvent extends Event<HuaWeiStore>{
public Date time;//事件发生时间
public HuaWeiStore store;//事件发生对象
public UpEvent(Date time, HuaWeiStore store){
this.time = time;
this.store = store;
}
public Date getTime(){
return time;
}
@Override
public HuaWeiStore getSource() {
return store;
}
}
/**
* 商店产品销售事件
*/
public class CellEvent extends Event<HuaWeiStore>{
public Date time;//事件发生时间
public HuaWeiStore store;//事件发生对象
public CellEvent(Date time, HuaWeiStore store){
this.time = time;
this.store = store;
}
public Date getTime(){
return time;
}
@Override
public HuaWeiStore getSource() {
return store;
}
}
/**
* 观察者基类
*/
public interface Observer {
//被观察者事件发生的业务处理
public void update(Event event);
}
/**
* 张三观察者
*/
public class ZsObserver implements Observer{
@Override
public void update(Event event) {
if(event instanceof UpEvent){//新产品上架事件
this.method1((UpEvent)event);
}else if(event instanceof CellEvent){//产品售罄事件
this.method2((CellEvent)event);
}
}
public void method1(UpEvent event){
System.out.println(event.getTime()+"点"+
event.getSource().getName()+"上架了最新华为手机。"+this.getClass()+"say:太晚了,明天去购买");
}
public void method2(CellEvent event){
System.out.println(event.getTime()+"点"+
event.getSource().getName()+"最新华为手机已售罄。"+this.getClass()+"say:昨天没买,亏大发了");
}
}
/**
* 李四观察者
*/
public class LsObserver implements Observer{
@Override
public void update(Event event) {
if(event instanceof UpEvent){//新产品上架事件
this.method1((UpEvent)event);
}else if(event instanceof CellEvent){//产品售罄事件
this.method2((CellEvent)event);
}
}
public void method1(UpEvent event){
System.out.println(event.getTime()+"点"+
event.getSource().getName()+"上架了最新华为手机。"+this.getClass()+"say:太远了,后面有事情路过再买");
}
public void method2(CellEvent event){
System.out.println(event.getTime()+"点"+
event.getSource().getName()+"最新华为手机已售罄。"+this.getClass()+"say:之前让商店附近的朋友帮买下就好了");
}
}
/**
* 王五观察者
*/
public class WwObserver implements Observer{
@Override
public void update(Event event) {
if(event instanceof UpEvent){//新产品上架事件
this.method1((UpEvent)event);
}else if(event instanceof CellEvent){//产品售罄事件
this.method2((CellEvent)event);
}
}
public void method1(UpEvent event){
System.out.println(event.getTime()+"点"+
event.getSource().getName()+"上架了最新华为手机。"+this.getClass()+"say:势在必得,马上启程去买");
}
public void method2(CellEvent event){
System.out.println(event.getTime()+"点"+
event.getSource().getName()+"最新华为手机已售罄。"+this.getClass()+"say:哈哈哈");
}
}
public class TestObserver {
public static void main(String[] args) throws InterruptedException {
HuaWeiStore huaWeiStore = new HuaWeiStore("华为营业厅(星达城店)");
huaWeiStore.subscribe(new ZsObserver());
huaWeiStore.subscribe(new LsObserver());
huaWeiStore.subscribe(new WwObserver());
huaWeiStore.newProductUp();
Thread.sleep(5000);
System.out.println("======================过了一天");
huaWeiStore.cellOut();
}
}
测试结果: