一、定义

 观察者设计模式定义了对象间的一种一对多的组合关系,以便一个对象的状态发生变化时,所有依赖于它的对象都得到通知并自动刷新。

 建立一个一(Subject)对多(Observer)的关系,能够使得当"一"变化的时候,依赖这个"一"的多也能够同步改变。

在JAVA语言的API中,提供了一个Observable抽象类以及一个Observer接口,构成JAVA语言对观察者模式的支持。

Observable抽象类   抽象主题角色,具体主题类必须继承该抽象类,同时抽象主题提供一个接口,可以增加和删除观察者对象以及一个消息通知方法。
Observer接口类,抽象观察者角色,具体观察者必须实现该接口,同时它定义了一个更新接口,具体观察者必须实现该更新方法。
观察者模式需要用到的Java类

  1 java.util.Observable 

    -able一般可能...的单词后缀,Observable就是可以被观察的,程序中的被观察者类,需要继承这个类。

  2 java.util.Observer

    这个是观察者,是接口。程序中的观察者类,需要实现这个接口中的update()方法。

二、角色

  • 抽象主题(Subject)角色:即被观察者(Observable)的角色,主题的抽象类,抽象主题角色把所有观察者对象的引用保存在一个集合里,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。
  • 具体主题(ConcreteSubject)角色:即具体被观察者(ConcreteObservable),此角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发出通知。
  • 抽象观察者(Observer)角色:此角色是观察者的接口类,它定义了一个更新接口,在得到主题的通知时更新自己。
  • 具体观察者(ConcreteObserver)角色:该主题实现抽象观察者角色所定义的更新接口,以便在主题的状态发生变化时更新自身的状态。

 三、场景展示

类图如下:

 

观察者对象User  一个接口类,必须实现update方法(获取更新消息)

package com.ssy.wlj.observer;

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

/**
 * 类说明: 微信用户是具体观察对象
 * @author happy
 * @since  2019年5月27日
 * 
 */
public class User implements Observer{
    private String name;
    public User(String name){
        this.name = name;
    }
 
    @Override
    public void update(Observable o, Object arg) {
        // TODO Auto-generated method stub
         System.out.println("微信用户:"+name+",您的微信公众号更新这些内容:"+arg);
    }

}

(2)被观察者对象OfficialAccount ,需要重写一个消息通知方法(publishnewInfo)

package com.ssy.wlj.observer;

import java.util.Observable;

/**
 * 类说明: OfficialAccount是具体被观察的对象:当它更新时,所有监听该对象的观察者(微信用户)都会接收到通知
 * @author happy
 * @since  2019年5月27日
 * 
 */
public class OfficialAccount extends Observable{
 
    /**
     * 
     * @param info  要给观察者的信息
     */
    public void publishNewInfo(String info){
 
        //标识这个Observable对象已经改变了,更具体来将就是把Observable中属性changed置为true.
        setChanged();
        //在通知所有观察者之前,需要判断Observable中属性changed是否为true,如若不为则不会发出通知。
        //具体可以看源码,蛮好理解的。
        notifyObservers(info);
    }

}

(3)测试主类

package com.ssy.wlj.observer;
/**
 * 类说明: 测试主类
 * @author happy 
 * @since  2019年5月27日
 * 
 */
public class Client {
    
    public static void main(String[] args) {
         //被观察的角色
        OfficialAccount officialAccount = new OfficialAccount();
 
        //观察者
        User userBob = new User("WeChat User-Bob");
        User userTom = new User("WeChat User-Tom");
        User userMe = new User("WeChat User-Me");
 
        //将观察者注册到可观察对象的观察者列表中
        officialAccount.addObserver(userBob);
        officialAccount.addObserver(userTom);
        officialAccount.addObserver(userMe);
 
        //发布消息
        officialAccount.publishNewInfo("...新内容...");
        officialAccount.deleteObserver(userMe);
        System.out.println("##########################################");
        officialAccount.publishNewInfo("...新内容123...");

    }

}

运行测试类:

微信用户:WeChat User-Me,您的微信公众号更新这些内容:...新内容...
微信用户:WeChat User-Tom,您的微信公众号更新这些内容:...新内容...
微信用户:WeChat User-Bob,您的微信公众号更新这些内容:...新内容...
##########################################
微信用户:WeChat User-Tom,您的微信公众号更新这些内容:...新内容123...
微信用户:WeChat User-Bob,您的微信公众号更新这些内容:...新内容123...

 场景展示二:

 创建 Subject 类

package com.ssy.wlj.observer;

import java.util.ArrayList;
import java.util.List;

/**
 * 类说明:
 * 
 * @author happy
 * @since 2019年5月27日
 * 
 */
public class Subject {

    private List<Observer> observers = new ArrayList<Observer>();
    private int state;

    public int getState() {
        return state;
    }

    public void setState(int state) {
        this.state = state;
        notifyAllObservers();
    }

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

    public void notifyAllObservers() {
        for (Observer observer : observers) {
            observer.update();
        }
    }

}

创建 Observer 类

package com.ssy.wlj.observer;

/**
 * 类说明:
 * 
 * @author happy
 * @since 2019年5月27日
 * 
 */
public abstract class Observer {
    protected Subject subject;

    public abstract void update();
}

创建实体观察者类

package com.ssy.wlj.observer;
/**
 * 类说明: 
 * @author happy
 * @since  2019年5月27日
 * 
 */
public class OctalObserver extends Observer{
     
       public OctalObserver(Subject subject){
          this.subject = subject;
          this.subject.attach(this);
       }
     
       @Override
       public void update() {
         System.out.println( "Octal String: " 
         + Integer.toOctalString( subject.getState() ) ); 
       }

}
package com.ssy.wlj.observer;
/**
 * 类说明: 
 * @author happy
 * @since  2019年5月27日
 * 
 */
public class BinaryObserver extends Observer{
         
           public BinaryObserver(Subject subject){
              this.subject = subject;
              this.subject.attach(this);
           }
         
           @Override
           public void update() {
              System.out.println( "Binary String: " 
              + Integer.toBinaryString( subject.getState() ) ); 
           }
}
package com.ssy.wlj.observer;
/**
 * 类说明: 
 * @author happy
 * @since  2019年5月27日
 * 
 */
public class HexaObserver extends Observer{
     
       public HexaObserver(Subject subject){
          this.subject = subject;
          this.subject.attach(this);
       }
     
       @Override
       public void update() {
          System.out.println( "Hex String: " 
          + Integer.toHexString( subject.getState() ).toUpperCase() ); 
       }

}

创建客户端:

package com.ssy.wlj.observer;
/**
 * 类说明: 
 * @author happy
 * @since  2019年5月27日
 * 
 */
public class Client {
    
    public static void main(String[] args) {
         Subject subject = new Subject();
         
          new HexaObserver(subject);
          new OctalObserver(subject);
          new BinaryObserver(subject);
     
          System.out.println("First state change: 15");   
          subject.setState(15);
          System.out.println("Second state change: 10");  
          subject.setState(10);
    }

}

测试结果:

First state change: 15
Hex String: F
Octal String: 17
Binary String: 1111
Second state change: 10
Hex String: A
Octal String: 12
Binary String: 1010

 

posted on 2019-05-27 10:57  友帅老师  阅读(137)  评论(0)    收藏  举报