Java设计模式——观察者模式

转自: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]  view plain  copy
  1. public interface Observer {  
  2.     public void update();  
  3. }  

两个实现类:

[java]  view plain  copy
  1. public class Observer1 implements Observer {  
  2.   
  3.     @Override  
  4.     public void update() {  
  5.         System.out.println("observer1 has received!");  
  6.     }  
  7. }  
[java]  view plain  copy
  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]  view plain  copy
  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]  view plain  copy
  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]  view plain  copy
  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]  view plain  copy
  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<Weather> list=new ArrayList<Weather>();
	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: Snow
Danielgo for job snowly.
Liligo for job snowly.
Ergougo to school snowly.
Sanyago to school snowly.
Current weather: Flog
Danielgo for job others.
Liligo for job others.
Ergougo to school others.
Sanyago to school others.
Current weather: Snow
Danielgo for job snowly.
Liligo for job snowly.
Ergougo to school snowly.
Sanyago to school snowly.
Current weather: Snow
Danielgo for job snowly.
Liligo for job snowly.
Ergougo to school snowly.
Sanyago to school snowly.
Current weather: Snow
Danielgo for job snowly.
Liligo for job snowly.
Ergougo to school snowly.
Sanyago to school snowly.



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值