[设计模式]1.Observer观测者模式-按钮事件模拟

这篇博客介绍了Observer观察者模式,详细讲解了模式的定义和组成,并通过模拟按钮响应事件的例子,展示了在Android应用开发中如何运用观察者模式。实例代码帮助读者理解观察者模式的基本原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Observer观察者模式定义

观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,让它们能够自动更新自己。这种模式最常用在我们熟悉的事件驱动模型里面,像VC、JAVA的swing,Android界面里面的事件响应,就是基于观察者模式来实现的。

Observer观察者模式的组成

观察者模式的类图如下:


可以看出,在这个观察者模式的实现里有下面这些角色:


抽象主题(Subject)角色:主题角色把所有对观察考对象的引用保存在一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象,主题角色又叫做抽象被观察者(Observable)角色,一般用一个抽象类或者一个接口实现。

抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。这个接口叫做更新接口。抽象观察者角色一般用一个抽象类或者一个接口实现。在这个示意性的实现中,更新接口只包含一个方法(即Update()方法),这个方法叫做更新方法。

具体主题(ConcreteSubject)角色:将有关状态存入具体现察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色又叫做具体被观察者角色(Concrete Observable)。具体主题角色通常用一个具体子类实现。

具体观察者(ConcreteObserver)角色:存储与主题的状态自恰的状态。具体现察者角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。如果需要,具体现察者角色可以保存一个指向具体主题对象的引用。具体观察者角色通常用一个具体子类实现。


Observer观察者模式模拟-按钮响应事件

下面我们写一个例子来模拟观察者模式的实现,大家就能清楚的看出观察者模式的基本原理。例子是button按钮的响应事件,在VC、Swing或者Android系统的界面设计中,每种控件的响应模式就是用的观察者模式。


新建一个Test.java的文件,由于该例子比较简单,所有的类我们都放在这个文件中。然后是Button类的实现(Button类相当于上图左侧的主题类和抽象主题,也就是被观察对象。Button类比较简单就未再写出抽象主题):

	private List<ActionListener>  actionListeners = new ArrayList<ActionListener>(); /*被观察对象中维护一个观察者链表,每次有新的观察者加入时调用addActionListener()即可增加到链表中 */
	
	public void buttonPressed() {     /* 按钮按下事件,激发观察者调用行为actionPerformed(),同时将发生的事件ActionEvent()传递给观察者*/
		for(int i=0; i<actionListeners.size();i++) {
			ActionListener l = actionListeners.get(i);
			ActionEvent e = new ActionEvent(System.currentTimeMillis());   /* 此刻事件类携带的就是发生按下按钮事件时的系统时间 */
			l.actionPerformed(e);
		}
	}


观察者Observer的实现,为interface接口:

interface ActionListener {
	public void actionPerformed(ActionEvent e);
}

具体观察者的实现,该处使用了三种观察者,每种在收到按钮事件发生时简单的打印一个字符串模拟事件的响应:

class myActionListener implements ActionListener {

	@Override
	public void actionPerformed(ActionEvent e) {
		System.out.println("按钮被按下了!! 时间是" + e.getWhen());
	}
	
}

class myActionListener2 implements ActionListener {

	@Override
	public void actionPerformed(ActionEvent e) {
		System.out.println("你点了确认键!!");
	}
	
}

class myActionListener3 implements ActionListener {

	@Override
	public void actionPerformed(ActionEvent e) {
		System.out.println("将要进入XX网站!!");
	}
	
}

最后是事件函数的定义,在被观察对象Button的按钮被点击时,触发ActionEvent事件传递给观察者,此时事件类就是获取系统的事件,传递给观察者。这样观察者可以针对传递过来的事件作出不同的响应:

class ActionEvent {
	
	private long when;
	
	public ActionEvent(long when) {
		super();
		this.when = when;
	}

	public String getWhen() {
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy年-MM月dd日-HH时mm分ss秒");
		Date date = new Date(when);
		return formatter.format(date);
	}
}

测试下该程序,写一个main函数:

public class Test {
	public static void main(String[] args) {
		Button b = new Button();  /* 建立一个被观察者 */
		b.addActionListener(new myActionListener());
		b.addActionListener(new myActionListener2());
		b.addActionListener(new myActionListener3());   /* 为该被观察者增加三个观察者对象 */
		b.buttonPressed();   /* 按钮按下,事件发生 */
	}
}

运行该程序,可以发现执行结果是三个观察者都观察到了按钮被按下的事件,每个观察者作出了不同的响应,其中第一个观察者获取到了事件类,也就是事件发生的系统时间



Android 应用开发中的观察者模式

在我们做Android应用的时候,会大量使用观察者模式,因为Framework层里面的事件驱动都是基于观察者模式实现的。另外在Framework层里面的各种服务在数据变更的时候,也是通过观察者模式实现上层数据更新。

Android里面最典型的观察者就是我们使用的各种控件监听者。例如下面对某个按钮的监听:
<span style="font-size:12px;">Button baiduclickButton = (Button)findViewById(R.id.button1);
//注册观察者baiduclickButton.setOnClickListener(new OnClickListener(){
//观察者实现    
@Override    
    public void onClick(View arg0)    {
        Log.d("Mythou_Log", "Click the button ");    
    }
});</span>

例如上面的代码,注册了一个按钮的监听方法。这里实际上是应用了一对一的观察者模式,setOnClickListener()方法就是注册一个观察者,Button对象就是我们要观察的目标对象。而new出来的OnClickListener(),就是我们实际的观察者。
  每当我们的目标按钮对象被点击,状态发生变化的时候,就会通过回调注册的OnClickListener观察者的onClick方法会来通知观察者,Button状态发生变化。这里的onClick相当于前面例子里面的update方法。下面是Android源码里面对OnClickListener的定义,跟我们前面定义一个观察者接口类似。
<span style="font-size:12px;">public interface OnClickListener     { 
       /**         
        * Called when a view has been clicked.         
        ** @param v The view that was clicked.         
       */              
       void onClick(View v);    
}</span>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值