Java设计模式开发中使用观察者模式的实例教程

作者:匆忙拥挤repeat 时间:2021-06-22 15:54:19 

观察者模式是软件设计模式中的一种,使用也比较普遍,尤其是在GUI编程中。关于设计模式的文章,网络上写的都比较多,而且很多文章写的也不错,虽然说有一种重复早轮子的嫌疑,但此轮子非彼轮子,侧重点不同,思路也不同,讲述方式也不近相同。
关键要素

主题:

主题是观察者观察的对象,一个主题必须具备下面三个特征。

  • 持有监听的观察者的引用

  • 支持增加和删除观察者

  • 主题状态改变,通知观察者

观察者:

当主题发生变化,收到通知进行具体的处理是观察者必须具备的特征。

为什么要用这种模式

这里举一个例子来说明,牛奶送奶站就是主题,订奶客户为监听者,客户从送奶站订阅牛奶后,会每天收到牛奶。如果客户不想订阅了,可以取消,以后就不会收到牛奶。

松耦合

观察者增加或删除无需修改主题的代码,只需调用主题对应的增加或者删除的方法即可。
主题只负责通知观察者,但无需了解观察者如何处理通知。举个例子,送奶站只负责送递牛奶,不关心客户是喝掉还是洗脸。
观察者只需等待主题通知,无需观察主题相关的细节。还是那个例子,客户只需关心送奶站送到牛奶,不关心牛奶由哪个快递人员,使用何种交通工具送达。

Java实现观察者模式
1. Java自带的实现
类图

Java设计模式开发中使用观察者模式的实例教程


/**
* 观察目标 继承自 java.util.Observable
* @author stone
*
*/
public class UpdateObservable extends Observable {

private int data;

public UpdateObservable(Observer observer) {
   addObserver(observer);
   /*
    * add other observer
    */
 }

public int getData() {
   return data;
 }

public void setData(int data) {
   if (data != this.data) {
     this.data = data;
     setChanged(); //标记 改变, 只有标记后才能通知到
     notifyObservers(); //通知
   }

}

@Override
 public synchronized void addObserver(Observer o) {
   super.addObserver(o);
 }

@Override
 public synchronized void deleteObserver(Observer o) {
   super.deleteObserver(o);
 }

@Override
 public void notifyObservers() {
   super.notifyObservers();
 }

@Override
 public void notifyObservers(Object arg) {
   super.notifyObservers(arg);
 }

@Override
 public synchronized void deleteObservers() {
   super.deleteObservers();
 }

@Override
 protected synchronized void setChanged() {
   super.setChanged();
 }

@Override
 protected synchronized void clearChanged() {
   super.clearChanged();
 }

@Override
 public synchronized boolean hasChanged() {
   return super.hasChanged();
 }

@Override
 public synchronized int countObservers() {
   return super.countObservers();
 }

}


/**
* 观察者 实现 java.util.Observer接口
* @author stone
*
*/
public class UpdateObserver implements Observer {

@Override
 public void update(Observable o, Object arg) {
   System.out.println("接收到数据变化的通知:");
   if (o instanceof UpdateObservable) {
     UpdateObservable uo = (UpdateObservable) o;
     System.out.print("数据变更为:" + uo.getData());
   }
 }

}

2. 自定义的观察模型
类图

Java设计模式开发中使用观察者模式的实例教程


/**
* 抽象观察者  Observer
* 观察 更新    
* @author stone
*
*/
public interface IWatcher {
 /*
  * 通知接口:
  * 1. 简单通知
  * 2. 观察者需要目标的变化的数据,那么可以将目标用作参数, 见Java的Observer和Observable
  */
// void update(IWatched watched);

void update();

}


/**
* 抽象目标 Subject
* 提供注册和删除观察者对象的接口, 及通知观察者进行观察的接口
* 及目标 自身被观察的业务的接口
* @author stone
*
*/
public interface IWatchedSubject {

public void add(IWatcher watch);

public void remove(IWatcher watch);

public void notifyWhatchers();

public void update();//被观察业务变化的接口
}


/**
* 具体观察者    Concrete Observer
*
* @author stone
*
*/
public class UpdateWatcher implements IWatcher {

@Override
 public void update() {
   System.out.println(this + "观察到:目标已经更新了");
 }

}

/**
* 具体目标角色  Concrete Subject
* @author stone
*
*/
public class UpdateWatchedSubject implements IWatchedSubject {
 private List<IWatcher> list;

public UpdateWatchedSubject() {
   this.list = new ArrayList<IWatcher>();
 }

@Override
 public void add(IWatcher watch) {
   this.list.add(watch);
 }

@Override
 public void remove(IWatcher watch) {
   this.list.remove(watch);
 }

@Override
 public void notifyWhatchers() {
   for (IWatcher watcher : list) {
     watcher.update();
   }
 }

@Override
 public void update() {
   System.out.println("目标更新中....");
   notifyWhatchers();
 }

}

* 是观察者的一种实现:
类图

Java设计模式开发中使用观察者模式的实例教程


/**
* 监听 用户在注册后
* @author stone
*
*/
public interface IRegisterListener {
 void onRegistered();
}


/**
* 监听 当用户登录后
* @author stone
*
*/
public interface ILoginListener {
 void onLogined();
}


/*
* * 是观察者模式的一种实现
* 一些需要监听的业务接口上添加 * ,调用 * 的相应方法,实现监听
*/
public class User {

public void register(IRegisterListener register) {
   /*
    * do ... register
    */
   System.out.println("正在注册中...");
   //注册后
   register.onRegistered();
 }

public void login(ILoginListener login) {
   /*
    * do ... login
    */
   System.out.println("正在登录中...");
   //登录后
   login.onLogined();
 }

}

/**
* 观察者(Observer)模式 行为型模式
*  观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时观察某一个目标对象。
*  这个目标对象在状态上发生变化时,会通知所有观察者对象,让它们能够自动更新自己
* 目标对象中需要有添加、移除、通知 观察者的接口
*  
* @author stone
*/
public class Test {

public static void main(String[] args) {
   /*
    * 使用Java自带的Observer接口和Observable类
    */
   UpdateObservable observable = new UpdateObservable(new UpdateObserver());
   observable.setData(99);
   System.out.println("");
   System.out.println("");
   /*
    * 自定义的观察者模型
    */
   IWatchedSubject watched = new UpdateWatchedSubject();
   watched.add(new UpdateWatcher());
   watched.add(new UpdateWatcher());
   watched.update();
   System.out.println("");

/*
    * 子模式- *
    */

User user = new User();
   user.register(new IRegisterListener() {

@Override
     public void onRegistered() {
       System.out.println("监听到注册后。。。");
     }
   });
   user.login(new ILoginListener() {

@Override
     public void onLogined() {
       System.out.println("监听到登录后。。。");
     }
   });

}
}

打印


接收到数据变化的通知:
数据变更为:99

目标更新中....
observer.UpdateWatcher@457471e0观察到:目标已经更新了
observer.UpdateWatcher@5fe04cbf观察到:目标已经更新了

正在注册中...
监听到注册后。。。
正在登录中...
监听到登录后。。。

标签:Java,设计模式,观察者模式
0
投稿

猜你喜欢

  • 打印Java程序的线程栈信息方式

    2021-11-02 19:00:28
  • java使用归并删除法删除二叉树中节点的方法

    2022-03-31 23:06:12
  • WPF实现文字粒子闪烁动画效果

    2022-01-12 23:56:45
  • java读取文件字符集示例方法

    2023-11-09 12:35:39
  • Java如何使用HTTPclient访问url获得数据

    2023-11-12 04:16:21
  • java编写Http服务器下载工具

    2021-11-08 08:07:38
  • Android自定义GestureDetector实现手势ImageView

    2023-12-18 05:16:35
  • java生成图片验证码示例程序

    2023-09-13 10:17:57
  • Java ArrayDeque使用方法详解

    2022-02-09 08:00:23
  • 可视化Swing中JTable控件绑定SQL数据源的两种方法深入解析

    2023-11-28 19:13:58
  • Android自定义View绘制的方法及过程(二)

    2023-05-02 14:42:17
  • C# Dynamic关键字之:调用属性、方法、字段的实现方法

    2022-09-22 04:23:39
  • C++实现扫雷游戏示例讲解

    2022-05-03 18:49:05
  • Java+opencv3.2.0实现人脸检测功能

    2022-11-27 10:36:42
  • 新手初学Java流程控制

    2023-08-23 08:12:34
  • Hadoop的安装与环境搭建教程图解

    2022-06-28 16:19:47
  • JAVA实现扫描线算法(超详细)

    2023-06-30 13:33:20
  • C#实现带百分比的进度条功能示例

    2023-09-08 14:17:03
  • springboot读取文件,打成jar包后访问不到的解决

    2023-07-14 13:56:35
  • Java如何在沙箱环境中测试支付宝支付接口

    2023-11-02 14:55:15
  • asp之家 软件编程 m.aspxhome.com