观察者模式/ java实现附代码 /

/注:场景和例子引用github上的设计模式。传送门:https://github.com/iluwatar/java-design-patterns/tree/master/observer

场景:

一个天气预报系统,凡是订阅了改天气预报的,当天气发生改变的时候就把通知发送给所有订阅该天气预报的人。如兽人族(Orcs)和霍比特人(Hobitts)订阅了该天气预报系统,当天气从晴变成雨天的时候,兽人族和霍比特人就收到了天气变成雨天的通知。 如果还有其他订阅了该天气预报的如人族(Terran),只需要在WeatherObserver中加入该人族(Terran)订阅者,这样当天气发生改变的时候,人族也会收到天气通知。

意图:

定义对象间的一对多关系,当一个对象发生状态更改时,会自动通知并更新所有依赖者。

具体实现:

         订阅天气预报系统的即是观察者(如Orcs、Hobitts),把这些订阅天气预报的人抽象成接口(WeatherObserver),所有订阅该天气预报的人都得实现这个接口才行。另外在天气类(Weather)中也得开放一个接口让他们订阅,如使用List<Subscriber> observers 和写一个方法 addObserver(WeatherObserver obs)来让他们订阅,一旦天气发生变化就通知所有订阅该天气的方法 notifyAllObserver()。

talk is cheap,show me the code............................................................................................................................................................................................................................................................(分割线)

先定义天气类型(WeatherType.java),定义为枚举类型(sunny,rainny,windy,clod)

public enum WeatherType {
     SUNNY,WINDY,CLOD,RAINY;

	 @Override
	 public String toString(){
		 return this.name().toLowerCase();
	 }
}

再将订阅者抽象成一个接口(WeatherObserver.java),所有订阅天气预报系统的必须实现这个接口。

public interface WeatherObserver {
      public void Upadate(WeatherType currentWeather);
}

天气类(Weather)负责定义数据结构来接收订阅者和通知更新订阅者天气变化。使用List<WeatherObserver>来接收订阅者,定义方法addObserver来接收新的订阅者和notifyAllObsever方法来更新订阅者天气状态。

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

public class Weather {
     private WeatherType currentWeather;
     private List<WeatherObserver> observers;

     public Weather(){
         observers=new ArrayList<>();
         currentWeather=WeatherType.SUNNY;
     }

     public void addObservers(WeatherObserver observer){
         observers.add(observer);
     }

     public void removeObservers(WeatherObserver observer){
         observers.remove(observer);
     }

     public  void timePasses(){
         WeatherType[] enumValues=WeatherType.values();
        /* for(WeatherType type:enumValues){
             System.out.println(type);
         }*/
         //改变天气,让天气的enum类型往后推一个
         currentWeather=enumValues[(currentWeather.ordinal() + 1) % enumValues.length];
         System.out.println("The weather change to  "+currentWeather);
         notifyAllObserver();
     }

     public void notifyAllObserver(){
         for(WeatherObserver obs: observers){
             obs.Upadate(currentWeather);
         }
     }
}

添加两个订阅天气预报的“人”,一个兽族(Orcs.java)一个霍比特人(Hobitts.java)。 如上面所说,要订阅该天气预报必须实现WeatherOberver接口。

public class Orcs implements WeatherObserver{

    @Override
    public void Upadate(WeatherType currentWeather) {
        switch(currentWeather){
        case CLOD:
            System.out.println("The orcs are freezing cold");
            break;
        case SUNNY:
            System.out.println("The sun hurts the orcs‘ eyes.");
            break;
        case RAINY:
            System.out.println("The orcs are dripping wet.");
            break;
        case WINDY:
            System.out.println("The orc smell almost vanishes in the wind.");
        default:
            break;
        }
    }

public class Hobbits implements WeatherObserver{

    @Override
    public void Upadate(WeatherType currentWeather) {
        switch(currentWeather){
        case CLOD:
            System.out.println("The Hobbits are freezing cold");
            break;
        case SUNNY:
            System.out.println("The sun hurts the Hobbits‘ eyes.");
            break;
        case RAINY:
            System.out.println("The Hobbits are dripping wet.");
            break;
        case WINDY:
            System.out.println("The Hobbits smell almost vanishes in the wind.");
        default:
            break;
        }
    }
}

写一个主类来测试一下改功能(App.java)

public class APP {
    public static void main(String[] args){
        Weather weather=new Weather();
        weather.addObservers(new Orcs());
        weather.addObservers(new Hobbits());

        //weather.addObservers(new Terran());

        weather.timePasses();

        //weather.timePasses();

    }
}

输出:(即天气从Sunny变成Windy的时候,订阅该天气的Orcs和Hobitts都收到了天气改变的通知)

The weather change to  windy
The orc smell almost vanishes in the wind.
The Hobbits smell almost vanishes in the wind.

在以下任何情况下使用观察者模式:

  • 抽象有两个方面,一个依赖于另一个。将这些方面封装在单独的对象中可以让您独立地更改和重用它们
  • 当更改一个对象需要更改其他对象时,您不知道需要更改多少个对象
  • 当一个对象应该能够通知其他对象,而不需要假设这些对象是谁。换句话说,你不希望这些对象紧密结合
时间: 2024-11-10 15:10:01

观察者模式/ java实现附代码 /的相关文章

单例模式/ java实现附代码 /

注: 场景和例子出自github的设计模式.传送门:https://github.com/iluwatar/java-design-patterns/tree/master/singleton 意图: 单例模式即使为了确保一个类只有一个实例,并提供一个全局访问点. 场景: 世界上只有一座象牙塔可以让巫师学习魔法,所有巫师都来到这座象牙塔进行修习.那么象牙塔就这里可以理解为单例.简单的来说就是只创建一个类的一个对象,这个象牙塔就可以理解为唯一对象. 实现: 想更好的理解单例模式,最好先了解一下ja

Android网络传输中必用的两个加密算法:MD5 和 RSA (附java完成测试代码)

MD5和RSA是网络传输中最常用的两个算法,了解这两个算法原理后就能大致知道加密是怎么一回事了.但这两种算法使用环境有差异,刚好互补. 一.MD5算法 首先MD5是不可逆的,只能加密而不能解密.比如明文是yanzi1225627,得到MD5加密后的字符串是:14F2AE15259E2C276A095E7394DA0CA9  但不能由后面一大串倒推出yanzi1225627.因此可以用来存储用户输入的密码在服务器上.现在下载文件校验文件是否中途被篡改也是用的它,原理参见:http://blog.c

大话设计模式_观察者模式(Java代码)

观察者模式:定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态发生变化时,会通知所有观察者对象,使他们自己能够自动更新自己.简单描述:1个Subject类(可以是抽象类可以是接口),可以有多个具体Subject类(继承抽象Subject),此具体Subject持有多个观察者的引用,在此具体Subject状态发生变化的时候调用这些观察者的相应方法.另外,这些持有的引用是抽象的,不是具体的,而这些引用所指向的对象时具体的观察者(即需要作出更新的具体观察者,这些具体

设计模式之第18章-观察者模式(Java实现)

设计模式之第18章-观察者模式(Java实现) 话说曾小贤,也就是陈赫这些天有些火,那么这些明星最怕的,同样最喜欢的是什么呢?没错,就是狗仔队.英文的名字比较有意思,是paparazzo,这一说法据说来自意大利电影<滴露牡丹开>中一个专门偷拍明星照片的一个摄影师的名字,“Paparazzo”,中文译为帕帕拉齐,俗语就是狗仔队.这些明星因狗仔队而荣,获得曝光率,也因狗仔队而损,被曝光负面新闻,不管怎么说,总之是“火起来了”,让明星们又爱又恨.(众人:鱼哥,你扯远了).咳咳,这个狗仔队其实嘛,也就

Android NDK开发篇(五):Java与原生代码通信(数据操作)

尽管说使用NDK能够提高Android程序的运行效率,可是调用起来还是略微有点麻烦.NDK能够直接使用Java的原生数据类型,而引用类型,由于Java的引用类型的实如今NDK被屏蔽了,所以在NDK使用Java的引用类型则要做对应的处理. 一.对引用数据类型的操作 尽管Java的引用类型的实如今NDK被屏蔽了,JNI还是提供了一组API,通过JNIEnv接口指针提供原生方法改动和使用Java的引用类型. 1.字符串操作 JNI把Java的字符串当作引用来处理,在NDK中使用Java的字符串,须要相

java中静态代码块的用法 static用法详解

(一)java 静态代码块 静态方法区别一般情况下,如果有些代码必须在项目启动的时候就执行的时候,需要使用静态代码块,这种代码是主动执行的;需要在项目启动的时候就初始化,在不创建对象的情况下,其他程序来调用的时候,需要使用静态方法,这种代码是被动执行的. 静态方法在类加载的时候 就已经加载 可以用类名直接调用比如main方法就必须是静态的 这是程序入口两者的区别就是:静态代码块是自动执行的;静态方法是被调用的时候才执行的.静态方法(1)在Java里,可以定义一个不需要创建对象的方法,这种方法就是

java 编程思想 22.11: java bean 案例代码

java 编程思想  22.11:   java bean 案例代码 thinking in java 4免费下载:http://download.csdn.net/detail/liangrui1988/7580155 package org.rui.swing.bean; import java.awt.Color; import java.awt.event.ActionListener; import java.awt.event.KeyListener; import org.rui.

(转)Java二进制指令代码解析

转自http://www.blogjava.net/DLevin/archive/2011/09/13/358497.html Java二进制指令代码解析 Java源码在运行之前都要编译成为字节码格式(如.class文件),然后由ClassLoader将字节码载入运行.在字节码文件中,指令代码只是其中的一部分,里面还记录了字节码文件的编译版本.常量池.访问权限.所有成员变量和成员方法等信息(详见Java字节码格式详解).本文主要简单介绍不同Java指令的功能以及在代码中如何解析二进制指令. Ja

分享JAVA用户权限管理框架源代码JAVA权限管理java源代码框架代码,学习有帮助

JAVA用户权限管理框架源代码JAVA权限管理java源代码框架代码,用户功能权限控制到菜单以及菜单的操作按钮 MyEclipse+JDK1.6+apache-tomcat-6.0.14+SQL2005/2008/2012 是一套非常成熟的框架程序,可直接用于大型系统.基础框架快速开发,及程序员学习. .兼容 IE6,7,8,9 /Firefox /Google Chrome 这些浏览器都测试过 支持3级菜单导航. 框架包括用户管理.菜单管理.角色管理.权限管理.日志管理等功能. 内容包括源代码