观察者模式

观察者模式在JDK中有了很好的支持,目前,开发者使用JDK提供的观察者模式有两种途径。
1. 被观察者继承Observerable父类;观察者实现Oberver接口。
2. 在EventObject中封装消息参数;然后,在EventListenr中实现监听者(观察者)的动作。

首先来看采用Observable实现的观察者模式。
在这个例子中,我们将以“北朝鲜”作为一个被观察者,而北朝鲜的一举一动都影响的着半岛的稳定。而中美作为世界的两个大国,更是时刻关注者北朝鲜的一举一动。因此,中国和美国,各自都是观察者。而北朝鲜的关注点,无非是“原子弹”和“金正日同志的健康”。因此,如果,朝鲜宣布,核爆成功,那么,这两个观察者就会分别发表声明;如果,金正日死了,那么,两个观察者在观察到这个消息之后,也会做出不同的表态。

封装了半岛局势的枚举:

/**
* 朝鲜半岛的关注点。
*
* @author hongxin.xu
* @version $Id: PeninsulaEnum.java, v 0.1 2012-1-2 下午3:46:10 hongxin.xu Exp $
*/
public enum PeninsulaEnum {

/** 试爆成功。 */
NUCLEAR,

/** 金哥Bye! */
KIMJIONIIDEAD;

}


被观察者(北朝鲜的实例),这里需要注意的是,被观察者,必须要继承Observable父类。该父类中提供了“添加监听器”、“删除监听器”、“触发监听器”的方法。注意,在触发监听器操作之前,必须设置变更状态。否则,监听器将不会被触发。

/**
* 被观察者的实例。
* <p>
* 伟大的北朝鲜政权,是世界各国关注的焦点。 因此,在这里将其作为一个被观察者的实例。
* </p>
*
* @author hongxin.xu
* @version $Id: ChinaObserver.java, v 0.1 2012-1-2 下午3:14:53 hongxin.xu Exp $
*/
public class NorthKoreaSubject extends Observable {
public static void main(String[] args) {
// 声明两个观察者。
Observer china = new ChinaObserver();
Observer american = new AmericanObserver();

// 添加观察者
NorthKoreaSubject northKoreaSubject = new NorthKoreaSubject();
northKoreaSubject.addObserver(china);
northKoreaSubject.addObserver(american);

// 触发事件。
System.out.println("Kim-Jong-II:我们有原子弹了思密达!");
northKoreaSubject.setPeninsulaEnum(PeninsulaEnum.NUCLEAR);

// 触发事件。
System.out.println("Kim-Jong-II:我挂了~~~");
northKoreaSubject.setPeninsulaEnum(PeninsulaEnum.KIMJIONIIDEAD);

}

/**
* @param peninsulaEnum
* the peninsulaEnum to set
*/
public void setPeninsulaEnum(PeninsulaEnum peninsulaEnum) {
// 设置状态位。
super.setChanged();

// 触发notify事件。
super.notifyObservers(peninsulaEnum);
}
}


下面给出两个观察者的实例:
1.中国

/**
* 中国作为一个观察者,时时刻刻关注着北朝鲜的动态。
*
* @author hongxin.xu
* @version $Id: ChinaObserver.java, v 0.1 2012-1-2 下午3:19:39 hongxin.xu Exp $
*/
public class ChinaObserver implements Observer {

/**
* @see java.util.Observer#update(java.util.Observable, java.lang.Object)
*/
@Override
public void update(Observable o, Object arg) {
if (arg instanceof PeninsulaEnum) {
PeninsulaEnum msg = (PeninsulaEnum) arg;
if (msg == PeninsulaEnum.KIMJIONIIDEAD) {
System.out.println(" --中国外交部发来唁电");
}
if (msg == PeninsulaEnum.NUCLEAR) {
System.out.println(" --中国外交部表示谴责!");
}
}
}

}


2.美国

public class AmericanObserver implements Observer {

/**
* @see java.util.Observer#update(java.util.Observable, java.lang.Object)
*/
@Override
public void update(Observable o, Object arg) {
if (arg instanceof PeninsulaEnum) {
PeninsulaEnum msg = (PeninsulaEnum) arg;
if (msg == PeninsulaEnum.KIMJIONIIDEAD) {
System.out.println(" --白宫表示毫无压力");
}
if (msg == PeninsulaEnum.NUCLEAR) {
System.out.println(" --白宫很生气,后果很严重");
}
}
}

}


至此,我们就利用Observable实现了一个观察者模式。其运行的结果为:

Kim-Jong-II:我们有核原子弹了思密达!
--白宫很生气,后果很严重
--中国外交部表示谴责!
Kim-Jong-II:我挂了~~~
--白宫表示毫无压力
--中国外交部发来唁电


以上是采用Observer/Observerable实现的观察者模式。在JDK中还有另外的一种,实现观察者模式的方法,那就是使用EventObject和EventListener。还是采用“北朝鲜”的例子,我们来进行说明:
首先,定义半岛局势的枚举

/**
* 定义半岛局势的枚举
*
* @author ibm
*
*/
public enum PeninsulaEnum {
UNCLEAN, KIMJIONIIDEAD;
}


然后,在PeninsulaSituation中封装对该枚举的引用。同时,实现的状态的设置。

/**
* 半岛局势实例。
*
* @author ibm
*
*/
public class PeninsulaSituation extends EventObject {

/**
*
*/
private static final long serialVersionUID = 1L;
/** 半岛枚举。 */
private PeninsulaEnum peninsulaEnum;

public PeninsulaSituation(Object source) {
super(source);
// TODO Auto-generated constructor stub
if (source instanceof PeninsulaEnum) {
peninsulaEnum = (PeninsulaEnum) source;
}
}

/**
* @return the peninsulaEnum
*/
public PeninsulaEnum getPeninsulaEnum() {
return peninsulaEnum;
}

/**
* @param peninsulaEnum
* the peninsulaEnum to set
*/
public void setPeninsulaEnum(PeninsulaEnum peninsulaEnum) {
this.peninsulaEnum = peninsulaEnum;
}

}


与采用Observer的方式不同,如果使用EventListener来进行观察。那么,就必须自己来实现观察者的管理和触发。因此,这里给出如下的观察者的实现:

/**
* 被观察者实例。
*
* @author ibm
*
*/
public class NorthKoreaSubject {
/** 保存观察者实例的容器。 */
private final Vector repo = new Vector();

/**
* 添加事件监听器。
*
* @param eventListener
*/
public synchronized void addEventListener(EventListener eventListener) {
repo.addElement(eventListener);
}

public void notifyListener(EventObject e) throws IllegalAccessException {
Object[] localArr;

if (repo == null) {
throw new IllegalAccessException("Vector is empty");
}

synchronized (this) {
if (!repo.isEmpty()) {
localArr = repo.toArray();
for (Object element : localArr) {
((GovernmentListener) element).handler(e);
}
}
}
}
}


至此,被观察者的实现完成了。下面对观察者的实现进行介绍。首先,EventListener是一个没有任何方法的标识接口,为了能够表示观察者需要统一完成的动作,我们需要自定出一个接口,该接口继承自EventListener接口。

/**
* 监听器实例。
*
* @author ibm
*
*/
public interface GovernmentListener extends EventListener {
/** 接口中包含了事件对象。 */
void handler(EventObject e);
}


同样,中国和美国分别是这两个接口的实现。

/**
* 监听器的实现,中国。
* @author ibm
*
*/
public class ChinaEventListener implements GovernmentListener {

@Override
public void handler(EventObject e) {
// TODO Auto-generated method stub
if (e instanceof PeninsulaSituation) {
PeninsulaEnum situation = ((PeninsulaSituation) e)
.getPeninsulaEnum();
if (situation == PeninsulaEnum.KIMJIONIIDEAD) {
System.out.println(" --中国外交部发来唁电");
}
if (situation == PeninsulaEnum.UNCLEAN) {
System.out.println(" --中国外交部表示谴责");
}
}
}

}



/**
* 监听器的实现,美国。
*
* @author ibm
*
*/
public class AmericanEventListener implements GovernmentListener {

@Override
public void handler(EventObject e) {
// TODO Auto-generated method stub
if (e instanceof PeninsulaSituation) {
PeninsulaEnum situation = ((PeninsulaSituation) e)
.getPeninsulaEnum();
if (situation == PeninsulaEnum.KIMJIONIIDEAD) {
System.out.println(" --白宫表示毫无压力");
}
if (situation == PeninsulaEnum.UNCLEAN) {
System.out.println(" --白宫很生气,后果很严重");
}
}
}

}


下面是测试类

/**
* 事件监听器启动实例。
*
* @author ibm
*
*/
public class EventListenerStartDemo {
private final static NorthKoreaSubject subject = new NorthKoreaSubject();

public static void main(String[] args) {

try {
EventListener china = new ChinaEventListener();
EventListener american = new AmericanEventListener();

subject.addEventListener(china);
subject.addEventListener(american);

EventObject event1 = new PeninsulaSituation(
PeninsulaEnum.KIMJIONIIDEAD);
EventObject event2 = new PeninsulaSituation(PeninsulaEnum.UNCLEAN);

System.out.println("Kim Jong II -- 我挂了");
subject.notifyListener(event1);

System.out.println("Kim Jong II -- 我们有原子弹了思密达");
subject.notifyListener(event2);

} catch (Exception e) {
e.printStackTrace();
}

}
}


其执行的结果是:

Kim-Jong-II:我们有核原子弹了思密达!
--白宫很生气,后果很严重
--中国外交部表示谴责!
Kim-Jong-II:我挂了~~~
--白宫表示毫无压力
--中国外交部发来唁电


以上是放假,闲来无事自娱自乐的一些整理,希望大家拍砖!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值