博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java设计模式——观察者模式
阅读量:4029 次
发布时间:2019-05-24

本文共 7944 字,大约阅读时间需要 26 分钟。

转自:http://www.cnblogs.com/shamgod/p/4588557.html

 一、概述

childe类中的是关联监听者dad的,若要再增加监听者,会很不方便,且要修改代码。好的方法是封装监听者类,用addListener()方法动态添加监听者

 二、代码

1.Test.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
class 
WakenUpEvent{
     
    
private 
long 
time;
    
private 
String location;
    
private 
Child source;
     
    
public 
WakenUpEvent(
long 
time, String location, Child source) {
        
super
();
        
this
.time = time;
        
this
.location = location;
        
this
.source = source;
    
}
 
    
public 
long 
getTime() {
        
return 
time;
    
}
 
    
public 
void 
setTime(
long 
time) {
        
this
.time = time;
    
}
 
    
public 
String getLocation() {
        
return 
location;
    
}
 
    
public 
void 
setLocation(String location) {
        
this
.location = location;
    
}
 
    
public 
Child getSource() {
        
return 
source;
    
}
 
    
public 
void 
setSource(Child source) {
        
this
.source = source;
    
}
     
     
}
 
class 
Child 
implements 
Runnable {
     
    
private 
List<WakenUpListener> wakenUpListeners = 
new 
ArrayList<WakenUpListener>();
     
    
public 
void 
addWakenUpListener(WakenUpListener wul){
        
wakenUpListeners.add(wul);
    
}
    
public 
void 
wakeUp(){
        
for
(
int 
i = 
0
; i < wakenUpListeners.size(); i++){
            
WakenUpListener l = wakenUpListeners.get(i);
            
l.actionToWakenUp(
new 
WakenUpEvent(System.currentTimeMillis(), 
"bed"
this
));
        
}
    
}
 
    
@Override
    
public 
void 
run() {
        
try 
{
            
Thread.sleep(
3000
);
        
catch 
(Exception e) {
            
e.printStackTrace();
        
}
        
wakeUp();
    
}
}
 
 
interface 
WakenUpListener {
    
public 
void 
actionToWakenUp(WakenUpEvent e);
}
 
class 
Dad 
implements 
WakenUpListener {
 
    
public 
void 
actionToWakenUp(WakenUpEvent e) {
        
System.out.println(
"Fedd the child"
);
    
}
     
}
 
class 
GrandFather 
implements 
WakenUpListener {
 
    
public 
void 
actionToWakenUp(WakenUpEvent e) {
        
System.out.println(
"抱孩子"
);
    
}
     
}
 
 
public 
class 
Test {
 
    
public 
static 
void 
main(String[] args) {
        
Child c = 
new 
Child();
        
c.addWakenUpListener(
new 
Dad());
        
c.addWakenUpListener(
new 
GrandFather());
        
new 
Thread(c).start();
    
}
}

  

三、运行结果

转自:http://blog.csdn.net/zhangerqing/article/details/8243942

典型应用:事件监听器

转自:http://www.cnblogs.com/java-my-life/archive/2012/05/16/2502279.html

在阎宏博士的《JAVA与模式》一书中开头是这样描述观察者(Observer)模式的:

  观察者模式是对象的行为模式,又叫发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。

  观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己。


15、观察者模式(Observer)

包括这个模式在内的接下来的四个模式,都是类和类之间的关系,不涉及到继承,学的时候应该 记得归纳,记得本文最开始的那个图。观察者模式很好理解,类似于邮件订阅和RSS订阅,当我们浏览一些博客或wiki时,经常会看到RSS图标,就这的意思是,当你订阅了该文章,如果后续有更新,会及时通知你。其实,简单来讲就一句话:当一个对象变化时,其它依赖该对象的对象都会收到通知,并且随着变化!对象之间是一种一对多的关系。先来看看关系图:

我解释下这些类的作用:MySubject类就是我们的主对象,Observer1和Observer2是依赖于MySubject的对象,当MySubject变化时,Observer1和Observer2必然变化。AbstractSubject类中定义着需要监控的对象列表,可以对其进行修改:增加或删除被监控对象,且当MySubject变化时,负责通知在列表内存在的对象。我们看实现代码:

一个Observer接口:

[java]   
  1. public interface Observer {  
  2.     public void update();  
  3. }  

两个实现类:

[java]   
  1. public class Observer1 implements Observer {  
  2.   
  3.     @Override  
  4.     public void update() {  
  5.         System.out.println("observer1 has received!");  
  6.     }  
  7. }  
[java]   
  1. public class Observer2 implements Observer {  
  2.   
  3.     @Override  
  4.     public void update() {  
  5.         System.out.println("observer2 has received!");  
  6.     }  
  7.   
  8. }  

Subject接口及实现类:

[java]   
  1. public interface Subject {  
  2.       
  3.     /*增加观察者*/  
  4.     public void add(Observer observer);  
  5.       
  6.     /*删除观察者*/  
  7.     public void del(Observer observer);  
  8.       
  9.     /*通知所有的观察者*/  
  10.     public void notifyObservers();  
  11.       
  12.     /*自身的操作*/  
  13.     public void operation();  
  14. }  
[java]   
  1. public abstract class AbstractSubject implements Subject {  
  2.   
  3.     private Vector<Observer> vector = new Vector<Observer>();  
  4.     @Override  
  5.     public void add(Observer observer) {  
  6.         vector.add(observer);  
  7.     }  
  8.   
  9.     @Override  
  10.     public void del(Observer observer) {  
  11.         vector.remove(observer);  
  12.     }  
  13.   
  14.     @Override  
  15.     public void notifyObservers() {  
  16.         Enumeration<Observer> enumo = vector.elements();  
  17.         while(enumo.hasMoreElements()){  
  18.             enumo.nextElement().update();  
  19.         }  
  20.     }  
  21. }  
[java]   
  1. public class MySubject extends AbstractSubject {  
  2.   
  3.     @Override  
  4.     public void operation() {  
  5.         System.out.println("update self!");  
  6.         notifyObservers();  
  7.     }  
  8.   
  9. }  

测试类:

[java]   
  1. public class ObserverTest {  
  2.   
  3.     public static void main(String[] args) {  
  4.         Subject sub = new MySubject();  
  5.         sub.add(new Observer1());  
  6.         sub.add(new Observer2());  
  7.           
  8.         sub.operation();  
  9.     }  
  10.   
  11. }  

输出:

update self!

observer1 has received!
observer2 has received!

 这些东西,其实不难,只是有些抽象,不太容易整体理解,建议读者:根据关系图,新建项目,自己写代码(或者参考我的代码),按照总体思路走一遍,这样才能体会它的思想,理解起来容易!

天气站广播天气(传智播客)

1)问题描述:编写一个气象站、一个工人or学生两个类;当气象站更新添加的时候,要通知人做出相应的处理;

实现方法:通过事件监听方式的实现

2)类结构:

广播类:WeatherStation

听众类:Emp  &&  Student

订阅天气预报的接口:Weather

测试类:WeatherMain

3)代码

WeatherStation.java

package com.dp.ood;import java.util.ArrayList;import java.util.Random;/*** * 观察者模式:事件监听 * @author admin * 需求:编写一个气象站、一个工人两个类;当气象站更新添加的时候, * 要通知人做出相应的处理 *  * 问题1:不能    出现 气象站更新了多次天气,然后人才做一次的处理 *  * 问题2:不能  气象站只能够通知一个人 * * 问题3:不能  只是服务于一种群体 *  * 观察者设计模式的步骤: * 	1.当目前对象发生指定动作时,要通知另外一个对象作出相应的处理, * 这时候应该把对方的相应处理方法定义在接口上; *  2.在当前对象维护的接口的引用,当当前对象发生指定的动作时即可调用接口中的方法 *  */public class WeatherStation {	String[] weathers={"Sun","Flog","Wind","Snow"};		//Current weather	String currentWeather;		//人	/*Emp e;	public WeatherStation(Emp e){		this.e=e;	}*/	ArrayList
list=new ArrayList
(); public void addListener(Weather e){ list.add(e); } //Start public void startWork() throws InterruptedException{ Random random=new Random(); new Thread(){ @Override public void run(){ while(true){//Update cycle: 1-1.5s updateWeather(); //e.notifyWeather(); for(Weather e:list){ e.notifyWeather(currentWeather); } int s=random.nextInt(501)+1000; try { Thread.sleep(s); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }.start(); } //Update weather public void updateWeather(){ Random random=new Random(); int index=random.nextInt(weathers.length); currentWeather=weathers[index]; System.out.println("Current weather: "+currentWeather); } }
Weather.java

package com.dp.ood;//订阅天气预报的接口public interface Weather {	void notifyWeather(String weather);}

Emp.java

package com.dp.ood;//人根据天气做出相应的处理public class Emp implements Weather{	String name;	public Emp(String name) {		super();		this.name = name;	}		//weathers={"Sun","Flog","Wind","Snow"};	public void notifyWeather(String weather){		if(weather.equals("Sun")){			System.out.println(name+"go for job Sunny.");		}else if(weather.equals("Snow")){			System.out.println(name+"go for job snowly.");		}else{			System.out.println(name+"go for job others.");		}			}}
Student.java
package com.dp.ood;public class Student implements Weather{	String name;	public Student(String name) {		super();		this.name = name;	}		//weathers={"Sun","Flog","Wind","Snow"};	public void notifyWeather(String weather){		if(weather.equals("Sun")){			System.out.println(name+"go to school Sunny.");		}else if(weather.equals("Snow")){			System.out.println(name+"go to school snowly.");		}else{			System.out.println(name+"go to school others.");		}			}}
WeatherMain.java

package com.dp.ood;public class WeatherMain {	public static void main(String[] args) throws InterruptedException {		//工人		Emp e=new Emp("Daniel");		Emp e2=new Emp("Lili");				Student s1=new Student("Ergou");		Student s2=new Student("Sanya");				WeatherStation station=new WeatherStation();		station.addListener(e);		station.addListener(e2);		station.addListener(s1);		station.addListener(s2);				station.startWork();			}}
4)测试结果
Current weather: SnowDanielgo for job snowly.Liligo for job snowly.Ergougo to school snowly.Sanyago to school snowly.Current weather: FlogDanielgo for job others.Liligo for job others.Ergougo to school others.Sanyago to school others.Current weather: SnowDanielgo for job snowly.Liligo for job snowly.Ergougo to school snowly.Sanyago to school snowly.Current weather: SnowDanielgo for job snowly.Liligo for job snowly.Ergougo to school snowly.Sanyago to school snowly.Current weather: SnowDanielgo for job snowly.Liligo for job snowly.Ergougo to school snowly.Sanyago to school snowly.

你可能感兴趣的文章
[Mac]Mac 操作系统 常见技巧
查看>>
苹果Swift编程语言入门教程【中文版】
查看>>
捕鱼忍者(ninja fishing)之游戏指南+游戏攻略+游戏体验
查看>>
iphone开发基础之objective-c学习
查看>>
iphone开发之SDK研究(待续)
查看>>
计算机网络复习要点
查看>>
Variable property attributes or Modifiers in iOS
查看>>
NSNotificationCenter 用法总结
查看>>
C primer plus 基础总结(一)
查看>>
剑指offer算法题分析与整理(一)
查看>>
剑指offer算法题分析与整理(三)
查看>>
部分笔试算法题整理
查看>>
Ubuntu 13.10使用fcitx输入法
查看>>
pidgin-lwqq 安装
查看>>
mint/ubuntu安装搜狗输入法
查看>>
C++动态申请数组和参数传递问题
查看>>
opencv学习——在MFC中读取和显示图像
查看>>
retext出现Could not parse file contents, check if you have the necessary module installed解决方案
查看>>
pyQt不同窗体间的值传递(一)——对话框关闭时返回值给主窗口
查看>>
linux mint下使用外部SMTP(如网易yeah.net)发邮件
查看>>