RelaxHeart王琦
作者RelaxHeart王琦2019-05-10 18:43
研发工程师, RelaxHeart

设计模式:观察者模式

字数 3715阅读 1027评论 0赞 0

原文链接:https://www.relaxheart.cn/to/master/blog?uuid=75

前言


观察者模式是非常常用的设计模式之一。在软件系统中,当一个对象的行为依赖于另外一个对象的状态时,观察者模式就相当有用了。若不适用观察者模式提供的通用结构,而需要实现其类似的功能,则只能在另外一个线程中不停的监听对象所依赖的状态。在一个复杂的系统中,可能会因此开启很多线程来实现这一功能,这将是系统的性能产生额外的负担。观察者模式的意义也就在此,它可以在单线程中,是某一对象,即使得知自身所依赖的状态的变化。

什么是观察者模式


观察者模式的经典结构如下图所示:
观察者模式结构图.png

观察者模式结构图.png

ISubject是被观察对象,它可以增加和删除观察者。IObserver是观察者对象,它依赖ISubject的状态变化。当ISubject状态发生变化时,会通过inform()方法通知观察者。

观察者模式的主要角色及作用:

`主题接口`:指被观察的对象。当其状态发生改变或者某事件发生时,它会将这个变化通知观察者,它维护了观察者所需要依赖的状态。

`具体主题`:具体主题实现了主题接口中的方法。如新增观者这、删除观者者和通知观察者。其内部维护了一个观察者列表。

`观察者接口`:观察者接口定义了观察者对象的基本方法。当依赖的状态发生变化时,主题接口就会调用观察者的update方法。

`具体观察者`:实现了观察者接口的update(),具体处理当被观察者状态改变时或者某一事件发生时的业务逻辑。

看下上述观察者结构对应的代码实现:
主题接口的实现:

/**
 * @Author: 王琦 <QQ.Eamil>1124602935@qq.com</QQ.Eamil>
 * @Date: 2019-4-30 0030 21:07
 * @Description: 主题接口 / 被观察者
 */
public interface ISubject {

    void attach(IObserver observer); // 添加观察者
    void detach(IObserver observer); // 删除观察者
    void inform();                   // 通知所有的观察者
}

观察者接口的实现:

/**
 * @Author: 王琦 <QQ.Eamil>1124602935@qq.com</QQ.Eamil>
 * @Date: 2019-4-30 0030 21:09
 * @Description: 观察者接口
 */
public interface IObserver {

    void update(Object event); // 更新事件
}

一个具体的主题实现,注意,它维护了观察者队列,提供了增加和删除观察者的方法,并通过inform()通知所有观察者。

/**
 * @Author: 王琦 <QQ.Eamil>1124602935@qq.com</QQ.Eamil>
 * @Date: 2019-4-30 0030 21:10
 * @Description: 一个具体的主题实现
 */
public class ConcreteSubject implements ISubject {

    Vector<IObserver> observers = new Vector<IObserver>();

    @Override
    public void attach(IObserver observer) {
        observers.addElement(observer);
    }

    @Override
    public void detach(IObserver observer) {
        observers.removeElement(observer);
    }

    @Override
    public void inform() {

        for (IObserver observer : observers){
            // 这里通知所有的观察者
            observer.update(null);
        }
    }
}

两个具体的观察者实现如下,当它监听的状态发生变化时,update()方法就会被主题回调,进而可以在观察者内部进行业务处理:

/**
 * @Author: 王琦 <QQ.Eamil>1124602935@qq.com</QQ.Eamil>
 * @Date: 2019-4-30 0030 21:13
 * @Description: 一个具体的观察者
 */
public class ConcreteObserver1 implements IObserver {

    @Override
    public void update(Object event) {
        System.out.println("observer1 receives information");
    }
}
/**
 * @Author: 王琦 <QQ.Eamil>1124602935@qq.com</QQ.Eamil>
 * @Date: 2019-4-30 0030 21:13
 * @Description: 一个具体的观察者
 */
public class ConcreteObserver2 implements IObserver {

    @Override
    public void update(Object event) {
        System.out.println("observer2 receives information");
    }
}

来,测试下,看看结果是否符合预期:

/**
 * @Author: 王琦 <QQ.Eamil>1124602935@qq.com</QQ.Eamil>
 * @Date: 2019-4-30 0030 21:15
 * @Description: 观察者模式测试
 */
public class SubjectObserverModelTest {

    public static void main(String[] args) {
        ISubject subject = new ConcreteSubject();
        IObserver observer1 = new ConcreteObserver1();
        IObserver observer2 = new ConcreteObserver2();

        // add 观察者
        subject.attach(observer1);
        subject.attach(observer2);
        // 通知
        subject.inform();

        System.out.println("----------------  分隔符  ---------------");

        // remove 观察者
        subject.detach(observer2);
        // 再次通知
        subject.inform();
    }
}

执行结果如下:
测试观察者模式执行结果.png

测试观察者模式执行结果.png

JDK提供了观察者模式


显然符合我们的预期。观察者模式是很简单,所以也比较常用,以至于JDK内部已经为开发人员准备了一套观察者模式的实现。它位于java.util包中,包括java.util.Observable类和java.util.Observer接口,他们的关系如下图所示:
JDK观察者模式关系图.png

JDK观察者模式关系图.png

在java.util.Observable类中,已经实现了主要的功能,如增加观察者、删除观察者和通知观察者,开发人员可以直接通过继承Observable使用这些功能。java.util.Observer接口是观察者接口,它的update()方法会在java.util.Observable的notifyObservers()方法中被回调,以获得最新的状态变化。通常在观察者模式中Observer接口总是应用程序的核心扩展对象,具体的业务逻辑总是会被封装在update()方法中。

总结


(1):观察者模式可以用于事件监听、通知发布等场合。可以确保观察者在不适用轮询监控的情况下,及时收到相关消息和事件。
(2):在JDK中已经实现了一套观察者模式,我们可以直接复用它。

如果觉得我的文章对您有用,请点赞。您的支持将鼓励我继续创作!

0

添加新评论0 条评论

Ctrl+Enter 发表

作者其他文章

相关文章

相关资料

X社区推广