现在的位置: 首页 > 综合 > 正文

Observer(观察者)模式 – 2

2012年12月01日 ⁄ 综合 ⁄ 共 4206字 ⁄ 字号 评论关闭

原帖地址:http://luoji10000.blog.163.com/blog/static/166439382201066111938180/?fromdm&fromSearch&isFromSearchEngine=yes

 

 

一、概述




Java
的设计模式很多,观察者模式被称为是模式中的皇后,而且Java
jdk也对它做了实现,可见该设计模式的重要位置。在图形化设计的软件中,为了实现视图和事件处理的分离,大多都采用了Observer模式,比如
Java的Swing,Flex的ActionScript等。在现实的应用系统中也有好多应用,比如像当当网、京东商城一类的电子商务网站,如果你对某
件商品比较关注,可以放到收藏架,那么当该商品降价时,系统给您发送手机短信或邮件。这就是观察者模式的一个典型应用,商品是被观察者,有的叫主体;关注
该商品的客户就是观察者。下面的一个事例将模拟这个应用。




GoF说道:Observer模式的意图是“定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新”。从这段话里我们可以得到两个信息,如下:





1, 观察者(具体执行操作的对象,有多个)


2, 被观察者(顾名思义是被观察的对象,如果该对象发生某些变化则通知观察者执行对应的操)





二、jdk中观察者模式解析





在java的util包中实现了该设计模式的框架,大部分应用都可以直接用它,当然了你也可以自己实现它,实际上就是一个被观察者的抽象类和一个观察者接口。我们先看一下jdk是如何实现的。被观察者的抽象类java.util.Observable

package java.util;


public class Observable {


private boolean changed = false;


private Vector obs;




//创建被观察者时就创建一个它持有的观察者列表,注意,这个列表是需要同步的。


public Observable() {


obs = new Vector();


}


/** 


* 添加观察者到观察者列表中去 


*/ 

public synchronized void addObserver(Observer o) {


if (o == null)


throw new NullPointerException();


if (!obs.contains(o)) {


obs.addElement(o);


}


}


/** 


* 删除一个观察者 


*/  

public synchronized void deleteObserver(Observer o) {


obs.removeElement(o);


}


public void notifyObservers() {


notifyObservers(null);


}


/** 

* 通知操作,即被观察者发生变化,通知对应的观察者进行事先设定的操作,这个方法接受一个参数,这个参数一直传到观察者里,以供观察者使用

*/  


public void notifyObservers(Object arg) {

Object[] arrLocal;

synchronized (this) {

if (!changed)

return;

arrLocal = obs.toArray();

clearChanged();

}

for (int i = arrLocal.length-1; i>=0; i--)

((Observer)arrLocal[i]).update(this, arg);

}


public synchronized void deleteObservers() {

obs.removeAllElements();

}


protected synchronized void setChanged() {

changed = true;

}


protected synchronized void clearChanged() {

changed = false;

}



public synchronized boolean hasChanged() {

return changed;

}


public synchronized int countObservers() {

return obs.size();

}

}


当我们自己的被观察者继承这个Observable类是,我们就自动的获取到被观察者的一切条件了。很方便是不是,这也是为什么sun要把Observable放到java.util包中的原因,就是为了方便开发者。


下面我们再看一下观察者的接口java.util.Observer

package java.util;

public interface Observer {


void update(Observable o, Object arg);


}



口中就只有一个方法,update,方法中有两个参数,Observable和一个object,第一个参数就是被观察的对象,而第二个参数就得看业务需
求了,需要什么就传进去什么。我们自己的观察者类必须实现这个方法,这样在被观察者调用notifyObservers操作时被观察者所持有的所有观察者
都会执行update操作了.

三、观察者模式应用


下面是一个book对象,它是一个被观察者,所以要继承Observable。


import java.util.Observable;


public class Book extends Observable {





private String name = "";


private double price = 0.0;


public String getName() {


return name;


}


public void setName(String name) {


this.name = name;


}

public double getPrice() {


return price;


}


public void setPrice(double price) {


this.price = price;


}


//当书的价格修改时调用该方法


public void modifyPrice(Book b) {


//调用父类的方法,改变被观察者的状态 


setChanged();


//通知客户该书已降价


notifyObservers(b);


}





}

下面是观察者对象,表示顾客的电子邮件,它实现了Observer接口。


import java.util.Observable;


import java.util.Observer;


public class BuyerEmail implements Observer {

private String buyerId = "";


private String email = "";

public String getBuyerId() {


return buyerId;


}


public void setBuyerId(String buyerId) {


this.buyerId = buyerId;


}


public String getEmail() {


return email;


}


public void setEmail(String email) {


this.email = email;


}


//该方法会被“被观察者的父类”既Observable调用


public void update(Observable o, Object arg) {


//这里做具体发电子邮件的操作


Book b = (Book)arg;


System.out.println("给顾客的发电子邮件:"+b.getName()+"降价了,目前价格为:"+b.getPrice());


}

}


下面是另一个观察者对象,表示顾客的手机,同样需要继承Observer接口


import java.util.Observable;


import java.util.Observer;


public class BuyerMobileMessage implements Observer {

private String buyerId = "";


private String mobileNo = "";

public String getBuyerId() {


return buyerId;


}


public void setBuyerId(String buyerId) {


this.buyerId = buyerId;


}


public String getMobileNo() {


return mobileNo;


}


public void setMobileNo(String mobileNo) {


this.mobileNo = mobileNo;


}


public void update(Observable o, Object arg) {


// TODO Auto-generated method stub


Book b = (Book)arg;


System.out.println("给顾客的发手机短信:"+b.getName()+"降价了,目前价格为:"+b.getPrice());


}

}


下面是调用类:


public class MainApp {

public static void main(String args[])


{


Book b1 = new Book();


b1.setName("<<Java设计模式>>");


b1.setPrice(45.00);//假设原价是60,现在是降价促销

//下面的观察者在实际的应用中可以从数据库或文件中读取


BuyerMobileMessage bm = new BuyerMobileMessage();


bm.setBuyerId("001");


bm.setMobileNo("13810500085");

BuyerEmail be = new BuyerEmail();


be.setBuyerId("001");


be.setEmail("dobodo@163.com");

//增加观察者,在实际应用中就是那些人对该书做了关注


b1.addObserver(bm);


b1.addObserver(be);

b1.modifyPrice(b1);


}


}

输出:


给顾客的发电子邮件:<<Java设计模式>>降价了,目前价格为:45.0


给顾客的发手机短信:<<Java设计模式>>降价了,目前价格为:45.0





知道上面的例子你看懂了没有,观察者模式实际上没什么高深的东西,就是运用了java的继承和接口,在被观察者的抽象类里设置一个状态标志,通过该标志判
断是否通知观察者对象。在学习该模式的同时,我们更应该学习java的继承和接口的灵活应用,其实所有的设计模式都是继承、接口、多态的灵活应用。

抱歉!评论已关闭.