设计模式之observer

面向对象的开发的一个主导原则是,在给定的应用程序中正确地划分任务。系统中的每个对象应该将重点放在问题域中的离散抽象上。简而言之,一个对象只应做一件事,而且要将它做好。这种方法可确保在对象之间划定清晰的界限,因而可提供更高的重用性和系统可维护性。

  一个特别重要的领域是用户界面和基础业务逻辑之间的交互。在应用程序的开发过程中,需要快速更改用户界面,并且不能对应用程序的其他部分产生连带影响,这是司空见惯的事。此外,业务要求也可能会发生变化,而这一切与用户界面无关。具有丰富开发经验的人都知道,在很多情况下,这两组要求都会发生变化。如果没有划分UI和应用程序其他部分,修改任一部分都会对整体造成不利的影响。

  很多应用程序都需要在用户界面和业务逻辑之间划分清晰的界限。因此,自GUI出现以后,很多面向对象的框架均支持将用户界面从应用程序的其他部分中划分出来。其中的大部分应用程序采用的设计模式几乎相同。这种模式通常称为观察者,它非常有助于在系统中各种对象之间划分清晰的界限。此外,还会经常看到在框架或应用程序中与UI无关的部分中使用这种解决方案。Observer模式的作用远远超过了其最初的想法。

虽然Observer模式有很多变体,但该模式的基本前提包含两个角色:观察者(observer)和主体(subject)(熟悉Smalltalk MVC的人将这些术语分别称为View和Model)。在用户界面的环境中,观察者是负责向用户显示数据的对象。另一方面,主体表示从问题域中模拟的业务抽象。正如图1中所描述的一样,在观察者和主体之间存在逻辑关联。当主体对象中发生更改时,(例如,修改实例变量),观察者就会观察这种更改,并相应地更新其显示。

例如,假定我们要开发一种简单的应用程序,来跟踪全天的股票价格。在此应用程序中,我们指定一个Stock类来模拟在NASDAQ交易的各种股票。该类包含一个实例变量,它表示在全天不同时段经常波动的股价。为了向用户显示此信息,应用程序使用一个StockDisplay类向stdout(标准输出)写信息。在此应用程序中,一个Stock类实例作为主体,一个StockDisplay类实例作为观察者。随着股价在交易日中随时间发生变化,Stock实例的当前股价也会发生变化(它怎样变化并不重要)。因为StockDisplay实例正在观察Stock实例,所以在这些状态发生变化(修改股价)时,就会向用户显示这些变化。

  通过使用这种观察过程,可以在Stock和StockDisplay类之间划分界限。假定应用程序的要求第二天发生变化,要使用基于窗体的用户界面。要启用此新功能,只需要构造一个新类StockForm作为观察者。无论发生什么情况,Stock类都不需要进行任何修改。事实上,它甚至不知道发生此类更改。类似地,如果需求变化要求Stock类从另一个来源检索股价信息(可能是从Web服务,而不是从数据库中检索),则StockDisplay类不需要进行修改。它只是继续观察Stock就够了。

接下来,结合个人的学习方式:给个特定的例子,该例子简单模拟了awt事件处理

interface MyActionListener{
//监听器接口,定义一个处理事件的统一入口,从概念上来说,就是观察者了
public void actionPerformed(MyActionEvent e);

}
接下来定义MyActionEvent类,表示事件类型以及相关的事件信息

class MyActionEvent{
protected Object source;//产生事件的源对象

long when;//产生事件的事件

public MyActionEvent(Object source){
//源对象在产生事件时,调用此构造方法
this.source = source;
}

public long getWhen(){
return when;
}

public Object getSource(){
return source;
}
}

接着我们定义一个鼠标事件MyMouseEvent,继承MyActionEvent类

class MyMouseEvent extends MyActionEvent{

public MyMouseEvent(Object source) {//继承父类的构造方法
super(source);
}
public MyMouseEvent(Object source,long when){
//创建一个带事件时间的构造方法,此方法也由事件源调用
this(source);
this.when = when;
}

}

有了这些,我们现在来创建被观察者,也就是事件源MyButton类

class MyButton{
List<MyActionListener> actionListeners = new ArrayList<MyActionListener>();//所注册的所有观察者
public void addActionListener(MyActionListener actionListener){//增加观察者
actionListeners.add(actionListener);
}
public void pressedButton(){//事件发生
MyMouseEvent e = new MyMouseEvent(this,System.currentTimeMillis());//创建一个相应的事件对象
for(MyActionListener listener:actionListeners){
listener.actionPerformed(e);//交由观察者处理
}
}
}

基本上有了这些,我们再来写一个简单的测试

public class Test {
public static void main(String[] args){
MyButton b = new MyButton();//创建事件源
b.addActionListener(new MyActionListener(){
public void actionPerformed(MyActionEvent e) {
System.out.println("button pressed");
}
});//这里使用了内部匿名类构造观察者,并注册给事件源
b.pressedButton();//事件发生
}

}

看到这里,大家是否有种似曾相识的感觉呀?没错了,这和我们在awt里常用的组件事件处理方式是一样的。原来awt用的也是observer呀。

先到此告一段落了,今天写了太多,上班都没怎么做事。。。汗一个
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值