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.



發佈了71 篇原創文章 · 獲贊 208 · 訪問量 81萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章