设计模式学习笔记(10)--观察者模式

1.观察者模式定义

       观察者模式(Observer Pattern):定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式又叫做发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。观察者模式是一种对象行为型模式。

2.UML图

(1).猫、狗与老鼠 假设猫是老鼠和狗的观察目标,老鼠和狗是观察者,猫叫老鼠跑,狗也跟着叫,使用观察者模式描述该过程

3.代码

猫,狗,老鼠的观察者模式

package com.wuhuiskiff.www.observer.code.cat;

import java.util.ArrayList;

/**
 * @Auther: 一叶扁舟
 * @Date: 2019/2/12 15:57
 * @Description:抽象的观察目标,即被观察者
 */
public abstract class MySubject {
    // 观察者集合
    protected ArrayList observers = new ArrayList();

    // 观察目标执行的抽象动作
    protected abstract void cry();

    public void attach(MyObserver observer){
        observers.add(observer);
    }

    public void detach(MyObserver observer){
        observers.remove(observer);
    }
}
package com.wuhuiskiff.www.observer.code.cat;

/**
 * @Auther: 一叶扁舟
 * @Date: 2019/2/12 16:05
 * @Description:
 * 猫、狗与老鼠
 *       假设猫是老鼠和狗的观察目标,老鼠和狗是观察者,猫叫老鼠跑,狗也跟着叫,
 *       使用观察者模式描述该过程。
 */
public class Cat extends MySubject{
    @Override
    protected void cry() {
        System.out.println("猫叫了3声。。。喵喵喵。。。");
        // 观察者立即响应
        observers.forEach(  observer ->{
            ((MyObserver)observer).response();
        });
    }
}
package com.wuhuiskiff.www.observer.code.cat;

/**
 * @Auther: 一叶扁舟
 * @Date: 2019/2/12 15:54
 * @Description:
 */
public interface MyObserver {
    void response();
}

 

package com.wuhuiskiff.www.observer.code.cat;

/**
 * @Auther: 一叶扁舟
 * @Date: 2019/2/12 15:56
 * @Description:
 */
public class Mouse implements  MyObserver {
    @Override
    public void response() {
        System.out.println("老鼠逃跑。。。。");
    }
}
package com.wuhuiskiff.www.observer.code.cat;

/**
 * @Auther: 一叶扁舟
 * @Date: 2019/2/12 15:55
 * @Description:狗观察者
 */
public class Dog implements MyObserver {
    @Override
    public void response() {
        System.out.println("狗咆哮叫。。。");
    }
}
package com.wuhuiskiff.www.observer.code.cat;

/**
 * @Auther: 一叶扁舟
 * @Date: 2019/2/12 16:11
 * @Description:
 */
public class Client {
    public static void main(String[] args) {
        MySubject subject = new Cat();
        Dog dog = new Dog();
        subject.attach(dog);
        subject.attach(new Dog());
        // 猫叫
        subject.cry();
        subject.attach(new Mouse());
        subject.detach(dog);
        subject.cry();
    }
}

(2).使用jdk中的观察者模式

package com.wuhuiskiff.www.observer.code.jdk;

import java.util.Observable;
import java.util.Observer;

/**
 * @Auther: 一叶扁舟
 * @Date: 2019/2/12 11:37
 * @Description:
 */
public class MyObserver implements Observer {
    @Override
    public void update(Observable observable, Object obj) {
        System.out.println("更新了对象");
        System.out.println("观察数量:" + observable.countObservers());
    }
}
package com.wuhuiskiff.www.observer.code.jdk;

import java.util.Observable;

/**
 * @Auther: 一叶扁舟
 * @Date: 2019/2/12 11:34
 * @Description:使用jdk中自带的观察者模式
 */
public class Person extends Observable {
    private String name;
    private int age;
    private String sex;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
        this.setChanged();
        this.notifyObservers();
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
        this.setChanged();
        this.notifyObservers();
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
        this.setChanged();
        this.notifyObservers();
    }
}
package com.wuhuiskiff.www.observer.code.jdk;

/**
 * @Auther: 一叶扁舟
 * @Date: 2019/2/12 11:40
 * @Description:
 */
public class Client {
    public static void main(String[] args) {
        Person person = new Person();
        //注册观察者
        MyObserver myObserver = new MyObserver();
        MyObserver myObserver1 = new MyObserver();
        person.addObserver(myObserver);
        person.addObserver(myObserver1);

        person.setName("一叶扁舟");
        person.setAge(22);
        person.setSex("男");

    }
}

4.优缺点

观察者模式的优点

  • 观察者模式可以实现表示层和数据逻辑层的分离,并定义了稳定的消息更新传递机制,抽象了更新接口,使得可以有各种各样不同的表示层作为具体观察者角色。
  • 观察者模式在观察目标和观察者之间建立一个抽象的耦合。
  • 观察者模式支持广播通信。 观察者模式符合“开闭原则”的要求。

观察者模式的缺点

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

5.运用

  • JDK1.1版本及以后的各个版本中,事件处理模型采用基于观察者模式的委派事件模型(Delegation Event Model, DEM)。 在DEM中,事件的发布者称为事件源(Event Source),而订阅者叫做事件监听器(Event Listener),在这个过程中还可以通过事件对象(Event Object)来传递与事件相关的信息,可以在事件监听者的实现类中实现事件处理,因此事件监听对象又可以称为事件处理对象。 事件源对象、事件监听对象(事件处理对象)和事件对象构成了Java事件处理模型的三要素。
  • 除了AWT中的事件处理之外,Java语言解析XML的技术SAX2以及Servlet技术的事件处理机制都基于DEM,它们都是观察者模式的应用。
  • 观察者模式在软件开发中应用非常广泛,如某电子商务网站可以在执行发送操作后给用户多个发送商品打折信息,某团队战斗游戏中某队友牺牲将给所有成员提示等等,凡是涉及到一对一或者一对多的对象交互场景都可以使用观察者模式。
  • MVC模式 MVC模式是一种架构模式,它包含三个角色:模型(Model),视图(View)和控制器(Controller)。观察者模式可以用来实现MVC模式,观察者模式中的观察目标就是MVC模式中的模型(Model),而观察者就是MVC中的视图(View),控制器(Controller)充当两者之间的中介者(Mediator)。当模型层的数据发生改变时,视图层将自动改变其显示内容。

6.总结

  1. 观察者模式定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式又叫做发布-订阅模式、模型-视图模式、源-监听器模式或从属者模式。观察者模式是一种对象行为型模式。
  2. 观察者模式包含四个角色:目标又称为主题,它是指被观察的对象;具体目标是目标类的子类,通常它包含有经常发生改变的数据,当它的状态发生改变时,向它的各个观察者发出通知;观察者将对观察目标的改变做出反应;在具体观察者中维护一个指向具体目标对象的引用,它存储具体观察者的有关状态,这些状态需要和具体目标的状态保持一致。
  3. 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个目标对象,当这个目标对象的状态发生变化时,会通知所有观察者对象,使它们能够自动更新。
  4. 观察者模式适用情况包括:一个抽象模型有两个方面,其中一个方面依赖于另一个方面;一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变;一个对象必须通知其他对象,而并不知道这些对象是谁;需要在系统中创建一个触发链。
  5. 在JDK的java.util包中,提供了Observable类以及Observer接口,它们构成了Java语言对观察者模式的支持。

猜你喜欢

转载自blog.csdn.net/u011662320/article/details/87208929