一:什么是观察者模式:

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

举个例子,很多人都会订阅天气预报,当气象台获得明天的天气情况(目标对象)时,就会短信通知订阅了天气预报的人(观察者),然后订阅者就会根据明天天气情况做出相应的处理(呆在家?出去踏青?出去购物...)

二:观察者模式的两个角色:

第一个角色:目标对象(subject),被观察者关注的对象,它的改变引起观察者的改变,例如上面提到的天气情况。

第二个角色:观察者(observer),一个或者多个,关注着目标对象的状态,例如上例的订阅了天气预报的人群。

三:观察者模式三种常见的角色场景:

1. 一个目标对象,一个观察者对象,比如只要你一个人订阅了天气预报

2. 一个目标对象,多个观察者对象,比如,你爸爸,你妈妈和你都订阅了天气预报

3. 多个目标对象,一个观察者对象,比如你一个人订阅了天气预报,还订阅了报纸

四:推模型和拉模型(后面的代码会有注释):

推模型:observer在执行update()方法时,获取的是subject传给它的具体参数,目标对象主动向观察者推送目标的详细信息。

拉模型:observer在执行update()方法时,获得的是subject传给它的一个subject对象,observer需要什么参数自己去取。

五:java代码实行观察者模式:

首先提供最基本的观察者模式代码框架:

1. 新建一个Subject父类

import java.util.ArrayList;
import java.util.List; /*
* 目标对象,他知道观察它的观察者,并提供注册(添加)和删除观察者的接口
*/
public class Subject {
//用来保存注册的观察者对对象
private List<Observer> observers = new ArrayList<Observer>(); //将观察者添加多list对象中
public void attch(Observer observer){
observers.add(observer);
} //删除集合中的指定观察者对象
public void delete(Observer observer){
observers.remove(observer);
} //向所有注册了的观察者通知消息
protected void notifyObserver() {
for(Observer observer:observers){
observer.update(this);
}
}
}

2. 新建一个具体Subject实现类

   
/*
* 具体的目标对象,负责把有关状态存入到相应的观察者对象
*/
public class ConcreteSubject extends Subject {
//目标对象的状态
private String subjectState; public String getSubjectState() {
return subjectState;
} public void setSubjectState(String subjectState) {
this.subjectState = subjectState;
this.notifyObserver();
} }

3. 新建一个Observer接口

/*
* 这是一个观察者接口,定义一个更新的接口给那些在目标发生改变时,被通知的对象
*/
public interface Observer { /*
* 更新接口
* subject传入的目标对象,方便获取目标对象的状态
*/
public void update(Subject subject); }

4. 新建一个observer实现类

/*
* 具体的观察者对象,实现更新的方法,使自身状态和目标状态一致
*/
public class ConcreteObserver implements Observer { private String observerState;
@Override
public void update(Subject subject) {
// TODO Auto-generated method stub
observerState = ((ConcreteSubject)subject).getSubjectState();
} }

下面我用一个具体的例子,来实现观察者模式,让你更加清晰了解观察者模式

一个这样的场景,小东的女朋友和老妈都订阅了小东开发的一个天气预报软件,当每天天气不同时,小东的女朋友和老妈收到天气情况通知,都会安排明天的行程。小东的这个软件可逗的女朋友和老妈开心了,原来程序猿还有这作用,下面来看程序如何演示的:

1. 新建一个WeatherSubject父目标对象

import java.util.ArrayList;
import java.util.List; /*
* 目标对象,他知道观察它的观察者,并提供注册(添加)和删除观察者的接口
*/
public class WeatherSubject {
//用来保存订阅天气的人
private List<Observer> observers = new ArrayList<Observer>(); //把订阅天气的人添加到订阅列表中
public void attch(Observer observer){
observers.add(observer);
} //删除集合中的指定的订阅天气的人
public void delete(Observer observer){
observers.remove(observer);
} //通知所有已经订阅了天气的人
protected void notifyObserver() {
for(Observer observer:observers){
observer.update(this);
}
}
}

2. 新建一个WeatherSubject具体实现对象( 观察者需要从目标对象中需要获取的的状态只有天气内容)

/*
* 具体的目标对象,负责把有关状态存入到相应的观察者对象
*/
public class ConcreteWeatherSubject extends WeatherSubject {
//获取天气的内容信息
private String weatherContent; public String getWeatherContent() {
return weatherContent;
} public void setWeatherContent(String weatherContent) {
this.weatherContent = weatherContent;
//内容有了,说明天气更新了,通知所有订阅的人
this.notifyObserver();
} }

3. 新建一个Observer接口

/*
* 这是一个观察者接口,定义一个更新的接口给那些在目标发生改变时,被通知的对象
*/
public interface Observer { /*
* 更新接口
* subject传入的目标对象,方便获取目标对象的状态
*/
public void update(WeatherSubject subject); }

4. 新建一个具体的WeatherSubject对象

/*
* 具体的观察者对象,实现更新的方法,使自身状态和目标状态一致
*/
public class ConcreteObserver implements Observer { //观察者的名字,是谁收到了这个讯息,小东女朋友还是他老妈
private String observerName; //天气内容的情况,这个消息从目标处获得
private String weatherContent; //提醒的内容,小东的女朋友提醒约会,而他老妈提醒购物
private String remindThing; public String getObserverName() {
return observerName;
}
public void setObserverName(String observerName) {
this.observerName = observerName;
}
public String getWeatherContent() {
return weatherContent;
}
public void setWeatherContent(String weatherContent) {
this.weatherContent = weatherContent;
}
public String getRemindThing() {
return remindThing;
}
public void setRemindThing(String remindThing) {
this.remindThing = remindThing;
} public void update(WeatherSubject subject) {
weatherContent = ((ConcreteWeatherSubject)subject).getWeatherContent();
System.out.println(observerName + "收到了" + weatherContent + ","+remindThing);
} }

5. 测试类

public class Client {
public static void main(String[] args) {
//1.创建目标
ConcreteWeatherSubject weatherSubject = new ConcreteWeatherSubject(); //2.创建观察者
ConcreteObserver observerGirl = new ConcreteObserver();
observerGirl.setObserverName("小东的女朋友");
observerGirl.setRemindThing("是我们的第一次约会,地点华罗利广场,不见不散额"); ConcreteObserver observerMom = new ConcreteObserver();
observerMom.setObserverName("小东的老妈");
observerMom.setRemindThing("是一个购物的好日子,明天去老街血拼");
//3.注册观察者
weatherSubject.attch(observerGirl);
weatherSubject.attch(observerMom); //4.目标发布天气
weatherSubject.setWeatherContent("明天天气晴朗,晴空万里,温度28℃");
}
}

6. 运行结果

各位程序猿屌丝们,原来观察者模式还能来泡妞,你还等什么了,现在对观察者模式有了基本的了解了吧。最后我们来谈谈哪些情况能用到观察者模式:

  • 当一个抽象模型有两个方面,其中一个方面的操作依赖与另一方面的状态变化就可以使用观察者模式。
  • 如果在更改一个状态的时候,需要同事连带改变其他对象,而且不知道有多少个对象需要被连带改变时,可以选用观察者模式。
  • 当一个对象必须通知其它对象,但你又希望这个对象和其它被它通知的对象是松散耦合的,也可以使用观察者模式。

谢谢各位看官的赏脸,我们下次再见!

新手码农浅谈观察者模式(java语言简单实现)的更多相关文章

  1. 20190608_浅谈go&java差异(三)

    20190608_浅谈go&java差异(三) 转载请注明出处https://www.cnblogs.com/funnyzpc/p/10990703.html 第三节内容概览 多线程通讯(线程 ...

  2. 20190312_浅谈go&java差异(一)

    多线程 java java中对于大量的比较耗时的任务多采用多线程对方式对任务进行处理,同时由于进程和线程 本身是通过宿主机OS进行管理的,当在cpu核数较少或线程分配不当 会导致多线程的效果不佳的事常 ...

  3. 浅谈C++/JAVA/C#运行机制和执行效率

    估计有很多同学都对C++/JAVA/C#这三大热门语言的运行机制和执行效率有或多或少的困惑,自己也有,但是经过前期的学习,了解了三者在这两方面的区别,就废话不说了,进入主题吧.         一.运 ...

  4. 浅谈对java中传参问题的理解

    之前用的c/c++比较多,在c/c++中对于传参类型,无外乎就是传值.传引用.传指针这几种.但在java中,由于没有指针类型,其传参的方式也发生了相应的变化.在网上找了找,按我之前的理解,java中传 ...

  5. 浅谈一下Java String

    相信很多同学使用Java String, Java中的String方法,但是对其中的原理可能有些模糊,那么咱们就针对这块内容进行展开,让更多的同学理解和知道. public final class S ...

  6. 浅谈在Java开发中的枚举的作用和用法

    枚举(enum),是指一个经过排序的.被打包成一个单一实体的项列表.一个枚举的实例可以使用枚举项列表中任意单一项的值.枚举在各个语言当中都有着广泛的应用,通常用来表示诸如颜色.方式.类别.状态等等数目 ...

  7. 浅谈PL/SQL语言基础

    在前面的学习中,我们大部分接触的都是SQL语言,但是,在实现复杂操作的时候,SQL语言就无能为力了,这时候就需要引入新的语言,PL/SQL语言就是对SQL语言的扩展,可以实现存储过程,函数等的创建.下 ...

  8. 浅谈:java泛型与dao重用

    在进入今天的主题之前,我们先理解一下什么是泛型: 泛型是java中一种类型,泛型是被参数化的类型. 类型-->class 参数化-->class类型可以是任意参数 泛型存在的意义:泛型可以 ...

  9. 浅谈用java解析xml文档(四)

    继续接上一文,这一阵子因为公司项目加紧,导致最后一个解析xml文档的方式,还没有总结,下面总结使用dom4J解析xml. DOM4J(Document Object Model for Java) 使 ...

随机推荐

  1. (转)apache和nginx的区别

    nginx 相对 apache 的优点: 轻量级,同样起web 服务,比apache 占用更少的内存及资源 抗并发,nginx 处理请求是异步非阻塞的,而apache 则是阻塞型的,在高并发下ngin ...

  2. jsexcel导出插件

    ExcelTable.js /* * author:wenluanlai */ (function ($) { Date.prototype.Format = function (fmt) { var ...

  3. Linux(Ubuntu 14.04) setting up OpenGL

    1. Install c/c++ compilation package. 2. install openGL and freeGlut library sudo apt-get install me ...

  4. TextMate 通用快捷键

    原来一直在Windows上使用notepad++文本编辑器,现在换了MAC,发现notepad++ 官方没有MAC版本的,在MAC上使用也有办法,只不过实在是太麻烦了. 通过查看网友的建议,发现了Te ...

  5. web工程关于500错误

    昨天一直被一个诡异问题困扰,解决了之后开心得的我连玩了一下午,哈哈哈哈哈哈哈哈-- 具体问题是这样的额,本地跑的贼正常,一发到测试服务器就报500错误,具体错误信息是.  HTTP Status 50 ...

  6. supervisor centos安装

    一.安装配置supervisor 1.安装python自动化工具    #yum install python-setuptools 2.#easy_install supervisor安装super ...

  7. HttpHandler

    HttpHandler初探 一.HttpHandler简介 HttpHandler是asp.net真正处理Http请求的地方.在这个HttpHandler容器中,ASP.NET Framework才真 ...

  8. 在 Windows 上安装 Laravel 5.x

    由于工作中要用到 Laravel ,所以在此记录以备忘. 下载并设置 PHP 进入 http://windows.php.net/download/ 下载 PHP 5.5.x 的最新版本.如果你用的是 ...

  9. OC基础--Xcode 模板修改和文档安装

    修改项目模板 项目模板就是创建工程的时候选择的某一个条目, Xcode会根据选择的条目生成固定格式的项目 如何修改项目模板 找到Xcode, 右键"显示包内容" 打开"/ ...

  10. AWS-CDH5.5安装-软件下载

    1.下载安装介质 下载CM安装文件: [root@ip---- cm5.5.0]# wget -c -r -nd -np -k -L -A rpm http://archive-primary.clo ...