java设计模式--观察者模式

本文通过一个具体的例子介绍了观察者模式的实现方式,包括被观察者和观察者的定义、交互过程及其实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 简介

    在实际生活中我们应该都有碰过过这个场景,那就是主题和订阅,一旦你订阅了主题,一有什么消息活动都会发送给你,

一个主题一般会有一个或多个订阅,这就是观察者模式了

2 实例

    其实jdk 的java.utils 包里就已经帮我们写好了被观察者的主要功能,我们只需要扩展就行了,源码我已经翻译了

3 UML

    

代码:

package com.sl.demo.Observable;


import java.util.Vector;

/**
 * 被观察者(主题)
 * @author pengkun
 *
 */
public class Observable {
	//标识(是否有发生改变)
    private boolean changed = false;
    //自动增长的对象数组
    private Vector<Observer> obs;

    
    /**
     * 构造行数初始化一个0个观察者自动增长的对象数组
     */
    public Observable() {
        obs = new Vector<>();
    }

   /**
    * 添加一个观察者(如果传入null就直接跑出NullPointerException异常)
    * @param o
    * 
    */
    public synchronized void addObserver(Observer o) {
        if (o == null)
            throw new NullPointerException();
        if (!obs.contains(o)) {
            obs.addElement(o);
        }
    }

    /**
     * 删除一个观察者
     * @param o
     */
    public synchronized void deleteObserver(Observer o) {
        obs.removeElement(o);
    }

    /**
     * 无参
     * 如果 hasChanged 方法指示对象已改变,则通知其所有观察者,并调用 clearChanged 方法来指示此对象不再改变。
     */
    public void notifyObservers() {
        notifyObservers(null);
    }

    /**
     * 有参
     * 如果 hasChanged 方法指示对象已改变,则通知其所有观察者,并调用 clearChanged 方法来指示此对象不再改变。
     */
    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();
    }

    /**
     * 
     * 标记此 Observable 对象为已改变
     */
    protected synchronized void setChanged() {
        changed = true;
    }

    /**
     *  指示对象不再改变,或者它已对其所有的观察者通知了最近的改变
     */
    protected synchronized void clearChanged() {
        changed = false;
    }

    /**
     * 判断对象是否改变
     * @return
     */
    public synchronized boolean hasChanged() {
        return changed;
    }

    /**
     * 返回观察者的个数
     * @return
     */
    public synchronized int countObservers() {
        return obs.size();
    }
}

package com.sl.demo.Observable;


/**
 * 被观察者(旭旭宝宝直播间)
 * @author pengkun
 *
 */
public class Subject extends Observable {
	/**
	 * 业务方法
	 */
	public void sendMassage(String massage) {
		if(true) {
			//标记此 Observable 对象为已改变的对象
			super.setChanged();
		}
		notifyObservers(massage);
	}
}

观察者接口

package com.sl.demo.Observable;


/**
 * 观察者接口
 * @author pengkun
 *
 */
public interface Observer {
	//只要被观察者(主题)对象改变了就调用此方法
	void update(Observable o, Object arg);
}
package com.sl.demo.Observable;

/**
 * 观察者
 * @author pengkun
 *
 */
public class JMSOvserver implements Observer {

	@Override
	public void update(Observable o, Object arg) {
		System.out.println("收到一条消息:"+arg);
	}

}

测试:
	@Test
	public void test() {
		//被观察这(主题:旭旭宝宝直播间)
		Subject subject=new Subject();
		//观察者(订阅人:观众)
		Observer observer1=new JMSOvserver();
		Observer observer2=new JMSOvserver();
		Observer observer3=new JMSOvserver();
		//订阅他装逼王直播间,好一有装B视频就能知道
		//现在有三个死肥仔订阅了他的直播间
		subject.addObserver(observer1);
		subject.addObserver(observer2);
		subject.addObserver(observer3);
		//现在老吊要直播了
		subject.sendMassage("增幅亡,强化亡,黑铁太上皇开始直播啦!感紧来围观");
		
		System.out.println("-------------------------------");
		//现在有个死肥仔取消订阅了
		subject.deleteObserver(observer3);
		subject.sendMassage("增幅亡,强化亡,黑铁太上皇开始直播啦!感紧来围观");
	}
结果:
收到一条消息:增幅亡,强化亡,黑铁太上皇开始直播啦!感紧来围观
收到一条消息:增幅亡,强化亡,黑铁太上皇开始直播啦!感紧来围观
收到一条消息:增幅亡,强化亡,黑铁太上皇开始直播啦!感紧来围观
-------------------------------
收到一条消息:增幅亡,强化亡,黑铁太上皇开始直播啦!感紧来围观
收到一条消息:增幅亡,强化亡,黑铁太上皇开始直播啦!感紧来围观

总结:

1)主题要知道哪些观察者对其进行监测,说明主题类中一定有一个集合类成员变量,添加和删除及判断这些观察者对象是否存在。

2)观察者类一定是多态的,有共同的父类接口。

3)主题完成的功能基本是固定的,添加观察者、撤销观察者、通知消息给观察者及引起观察者响应(即“拉”数据),可以抽象出来




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值