• 【设计模式】观察者模式Observer Pattern


    目录

    遇到问题

    梳理需求

    观察者模式的实现

    JDK中的实现


    遇到问题

    当一个对象发生修改时,需要通知多方。

    很自然就会想到回调,这个就是观察者模式的核心,观察者模式可以将大量的回调解耦,从而使代码更加优雅。

    梳理需求

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

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

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

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

    关键代码:在抽象类里有一个 ArrayList 存放观察者们。

    观察者模式的实现

    1. import java.util.ArrayList;
    2. import java.util.List;
    3. public class Subject {
    4. private List observers
    5. = new ArrayList();
    6. private int state;
    7. public int getState() {
    8. return state;
    9. }
    10. public void setState(int state) {
    11. this.state = state;
    12. notifyAllObservers();
    13. }
    14. public void attach(Observer observer){
    15. observers.add(observer);
    16. }
    17. public void notifyAllObservers(){
    18. for (Observer observer : observers) {
    19. observer.update();
    20. }
    21. }
    22. }

     接下来定义它的观察者们

    1. public abstract class Observer {
    2. protected Subject subject;
    3. public abstract void update();
    4. }

    编写Observer的实现类

    1. public class BinaryObserver extends Observer{
    2. public BinaryObserver(Subject subject){
    3. this.subject = subject;
    4. this.subject.attach(this);
    5. }
    6. @Override
    7. public void update() {
    8. System.out.println( "Binary String: "
    9. + Integer.toBinaryString( subject.getState() ) );
    10. }
    11. }
    1. public class OctalObserver extends Observer{
    2. public OctalObserver(Subject subject){
    3. this.subject = subject;
    4. this.subject.attach(this);
    5. }
    6. @Override
    7. public void update() {
    8. System.out.println( "Octal String: "
    9. + Integer.toOctalString( subject.getState() ) );
    10. }
    11. }
    1. public class HexaObserver extends Observer{
    2. public HexaObserver(Subject subject){
    3. this.subject = subject;
    4. this.subject.attach(this);
    5. }
    6. @Override
    7. public void update() {
    8. System.out.println( "Hex String: "
    9. + Integer.toHexString( subject.getState() ).toUpperCase() );
    10. }
    11. }

    使用

    1. public class ObserverPatternDemo {
    2. public static void main(String[] args) {
    3. Subject subject = new Subject();
    4. new HexaObserver(subject);
    5. new OctalObserver(subject);
    6. new BinaryObserver(subject);
    7. System.out.println("First state change: 15");
    8. subject.setState(15);
    9. System.out.println("Second state change: 10");
    10. subject.setState(10);
    11. }
    12. }

    JDK中的实现

    Java的JDK中,已经实现观察者模式的相关代码

    JDK中提供了Observable抽象类、以及Observer接口

    Observable:可被观察的

    主要包含两个方法:

    setChanged()

    每次状态发生变更,都需要手动调用setChanged

    如果需要通知观察者,则需要调用

    notifyObservers()

    注意:如果在调用notifyObservers()方法之前没有调用setChanged()方法,就不会有什么动作发生。

    notifyObservers()方法中包含clearChanged()方法,将标志变量置回原值。

    notifyObservers()方法采用的是从后向前的遍历方式,即最后加入的观察者最先被调用update()方法。

    1. package com.learnjava.observer;
    2. import java.util.Observable;
    3. import java.util.Observer;
    4. class WatchedCounter extends Observable
    5. {
    6. public void countdown(int number)
    7. {
    8. for (; number >= 0; --number)
    9. {
    10. // 设置改变变量
    11. setChanged();
    12. // 通知所有观察者,将number作为参数信息传递给观察者
    13. notifyObservers(number);
    14. }
    15. }
    16. }
    17. class Watcher1 implements Observer
    18. {
    19. @Override
    20. public void update(Observable arg0, Object arg1)
    21. {
    22. System.out.println("Watcher1's number: " + arg1);
    23. }
    24. }
    25. class Watcher2 implements Observer
    26. {
    27. @Override
    28. public void update(Observable arg0, Object arg1)
    29. {
    30. if (((Integer) arg1).intValue() <= 5)
    31. {
    32. System.out.println("Watcher2's number: " + arg1);
    33. }
    34. }
    35. }
    36. public class ObserverTest
    37. {
    38. public static void main(String[] args)
    39. {
    40. WatchedCounter watchedCounter = new WatchedCounter();
    41. Watcher1 watcher1 = new Watcher1();
    42. Watcher2 watcher2 = new Watcher2();
    43. //添加观察者
    44. watchedCounter.addObserver(watcher1);
    45. watchedCounter.addObserver(watcher2);
    46. //开始倒数计数
    47. watchedCounter.countdown(10);
    48. }
    49. }

  • 相关阅读:
    http/https服务器实现
    如何使用DotNet-MetaData识别.NET恶意软件源码文件元数据
    userver-framework/userver
    kernel-4.0 定时器使用问题在kernel-4.19上纠正
    backward问题记录
    学生个人网页设计作品:旅游网页设计与实现——成都旅游网站4个页HTML+CSS web前端网页设计期末课程大作业 学生DW静态网页设计 学生个人网页设计作品
    vue中的 render 和 h() 详解
    Qt扩展-QCustomPlot绘图基础概述
    Linux入门第一天——linux基本概念
    3d可视化智慧园区设计成本
  • 原文地址:https://blog.csdn.net/asdf23d/article/details/136141770