面试官喜欢问的 设计模式之观察者模式

写在前面: 我是「扬帆向海」,这个昵称来源于我的名字以及女朋友的名字。我热爱技术、热爱开源、热爱编程。技术是开源的、知识是共享的

这博客是对自己学习的一点点总结及记录,如果您对 Java算法 感兴趣,可以关注我的动态,我们一起学习。

用知识改变命运,让我们的家人过上更好的生活

在这里插入图片描述

一、定义与组成部分

1. 定义

观察者(Observer)模式 又名发布-订阅(Publish/Subscribe)模式。GOF 给观察者模式如下定义:

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

面向对象设计的一个重要原则——单一职责原则。系统的每个对象应该将重点放在问题域中的离散抽象上。因此理想的情况下,一个对象只做一件事情。这样在开发中也就带来了诸多的好处:提供了重用性和维护性,也是进行重构的良好的基础。

2. 组成部分

观察者模式由以下几部分组成

  1. 抽象目标角色(Subject):目标角色知道它的观察者,可以有任意多个观察者观察同一个目标。并且提供注册和删除观察者对象的接口。目标角色往往由抽象类或者接口来实现。
  2. 抽象观察者角色(Observer):为那些在目标发生改变时需要获得通知的对象定义一个更新接口。抽象观察者角色主要由抽象类或者接口来实现。
  3. 具体目标角色(Concrete Subject):将有关状态存入各个Concrete Observer 对象。当它的状态发生改变时, 向它的各个观察者发出通知。
  4. 具体观察者角色(Concrete Observer):存储有关状态,这些状态应与目标的状态保持一致。实现Observer 的更新接口以使自身状态与目标的状态保持一致。在本角色内也可以维护一个指向Concrete Subject 对象的引用。

使用观察者模式的类图,这样能将关系清晰的表达出来。

在这里插入图片描述

在 Subject 这个抽象类中,提供了上面提到的功能,而且存在一个通知方法:notify。

还可以看到Subject 和ConcreteSubject 之间可以说是使用了模板模式(这个模式真是简单普遍到一不小心就用到了)。

这样当具体目标角色的状态发生改变,按照约定则会去调用通知方法,在这个方法中则会根据目标角色中注册的观察者名单来逐个调用相应的update 方法来调整观察者的状态。

这样观察者模式就走完了一个流程。

二、实现观察者模式

MySubject类就是我们的主对象,Observer1和Observer2是依赖于MySubject的对象,当MySubject变化时,Observer1和Observer2必然变化。

AbstractSubject类中定义着需要监控的对象列表,可以对其进行修改:增加或删除被监控对象,且当MySubject变化时,负责通知在列表内存在的对象。

Observer接口

public interface Observer {
    public void update();
}

实现类:Observer1

public class Observer1 implements Observer {
    @Override
    public void update() {
        System.out.println("observer1 接收到了!");
    }
}

实现类:Observer2

public class Observer2 implements Observer{
    @Override
    public void update() {
        System.out.println("observer2 接收到了!");
    }
}

Subject接口

public interface Subject {

    /**
     * 增加观察者
     *
     * @param observer
     */
    public void add(Observer observer);

    /**
     * 删除观察者
     * @param observer
     */
    public void del(Observer observer);

    /**
     * 通知所有的观察者
     */
    public void notifyObservers();

    /**
     * 自身的操作
     */
    public void operation();
}

Subject实现类

public abstract class AbstractSubject implements Subject {
    private Vector<Observer> vector = new Vector<Observer>();

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

    @Override
    public void del(Observer observer) {
        vector.remove(observer);
    }

    @Override
    public void notifyObservers() {
        Enumeration<Observer> enumo = vector.elements();
        while (enumo.hasMoreElements()) {
            enumo.nextElement().update();
        }
    }

    @Override
    public void operation() {

    }
}

MySubject类

public class MySubject extends AbstractSubject {
    @Override
    public void operation() {
        System.out.println("主对象的状态发生了改变!");
        notifyObservers();
    }
}

测试类:

public class Test {
    public static void main(String[] args) {
        Subject subject = new MySubject();
        subject.add(new Observer1());
        subject.add(new Observer2());
        subject.operation();
    }
}

测试结果:

在这里插入图片描述

三、 总结

  1. 观察者模式 主要解决了什么问题?

一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。

  1. 如何解决?

使用面向对象技术,可以将这种依赖关系弱化。

  1. 观察者模式 何时使用?

一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。

  1. 观察者模式 的优缺点

【优点】

① 观察者和被观察者是抽象耦合的。
② 建立一套触发机制。

【缺点】

① 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
②如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
③ 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

  1. 观察者模式 的使用场景

一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。

一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。

一个对象必须通知其他对象,而并不知道这些对象是谁。

需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。

  1. 观察者模式 的注意事项

① JAVA 中已经有了对观察者模式的支持类。
② 避免循环引用。
③ 如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。


由于水平有限,博客中难免会有一些错误,有纰漏之处恳请各位大佬不吝赐教!

1) 优秀程序应该是这样:阅读时,感觉很优雅;新增功能时,感觉很轻松;运行时,感觉很快速,这就需要设计模式支撑。<br /> <br /> 2) 设计模式包含了大量编程思想,讲授和真正掌握并不容易,网上设计模式课程不少,大多讲解比较晦涩,没有真实应用场景和框架源码支撑,学习后,只知其形,不知其神。就会造成这样结果: 知道各种设计模式,但是不知道怎么使用到真实项目。本课程针对上述题,有针对性进行了升级 (1) 授课方式采用 图解+框架源码分析方式,让课程生动有趣好理解 (2) 系统全面讲解了设计模式,包括 设计模式七大原则、UML类图-类六大关系、23种设计模式及其分类,比如 单例模式8种实现方式、工厂模式3种实现方式、适配器模式3种实现、代理模式3种方式、深拷贝等<br /> <br /> 3) 如果你想写出规范、漂亮程序,就花时间来学习下设计模式吧<br /> <br /> 课程内容和目标<br /> <br /> 本课程是使用Java来讲解设计模式,考虑到设计模式比较抽象,授课采用 图解+框架源码分析方式<br /> <br /> 1) 内容包括: 设计模式七大原则(单一职责、接口隔离、依赖倒转、里氏替换、开闭原则、迪米特法则、合成复用)、UML类图(类依赖、泛化和实现、类关联、聚合和组合) 23种设计模式包括:创建型模式:单例模式(8种实现)、抽象工厂模式、原型模式、建造者模式、工厂模式。结构型模式:适配器模式(3种实现)、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式(3种实现)。行为型模式:模版方法模式、命令模式、访模式、迭代器模式观察者模式、中介者模式、备忘录模式、解释器模式(Interpreter模式)、状态模式、策略模式、职责链模式(责任链模式)<br /> <br /> 2) 学习目标:通过学习,学员能掌握主流设计模式,规范编程风格,提高优化程序结构和效率能力。<br /> <div> <br /> </div>
相关推荐
©️2020 CSDN 皮肤主题: 代码科技 设计师:Amelia_0503 返回首页