java:从消息机制谈到观察者模式

本文接编程思想之消息机制,读者可以结合编程思想之消息机制一起阅读,也可以直接从本文开始阅读。

从简单的例子开始

同样,我们还是先看一个简单例子:创建一个窗口实现加法的计算功能。其效果如下:

图1: 加法计算

Calculator.java:

import javax.swing.*;import javax.swing.border.BevelBorder;import java.awt.*;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;/** * Created with IntelliJ IDEA. * User: luoweifu * Date: 15-5-5 * Time: 下午9:14 * To change this template use File | Settings | File Templates. */{/*** 主窗口的宽度*/WIDTH = 500;/*** 主窗口的高度*/HEIGHT = 100;private JFrame frameCalculator;private JEditorPane editAddend1;private JEditorPane editAddend2;private JEditorPane editResult;private JLabel labelPlus;private JButton btEqual;public Calculator() {frameCalculator = new JFrame();}() {frameCalculator.setSize(WIDTH, HEIGHT);frameCalculator.setLocationRelativeTo(null);frameCalculator.setTitle(“加法计算”);Container container = frameCalculator.getContentPane();container.setLayout(new FlowLayout(FlowLayout.CENTER, 10, 10));editAddend1 = new JEditorPane();editAddend1.setBorder(new BevelBorder(BevelBorder.LOWERED));editAddend2 = new JEditorPane();editAddend2.setBorder(new BevelBorder(BevelBorder.LOWERED));labelPlus = new JLabel(“+”);btEqual = new JButton(“=”);editResult = new JEditorPane();editResult.setBorder(new BevelBorder(BevelBorder.LOWERED));editResult.setEditable(false);container.add(editAddend1);container.add(labelPlus);container.add(editAddend2);container.add(btEqual);container.add(editResult);frameCalculator.setVisible(true);//frameCalculator.setDefaultCloseOperation(EXIT_ON_CLOSE);class AdditionCalculate implements ActionListener {(ActionEvent e) {int add1 = Integer.parseInt(editAddend1.getText());int add2 = Integer.parseInt(editAddend2.getText());int result = add1 + add2;editResult.setText(result + “”);}}AdditionCalculate additionCalculate = new AdditionCalculate();btEqual.addActionListener(additionCalculate);}(String args[]) {Calculator calculator = new Calculator();calculator.launchFrame();}}

上面这个例子中,窗口和所有的控件创建完成之后,btEqual按钮邦定了一个监听对象additionCalculate,一旦这个按钮被点击,就会通知additionCalculate对象,additionCalculate对象监听到点击事件,就会调用actionPerformed方法作出相应的响应。additionCalculate是内部类AdditionCalculate的对象,AdditionCalculate实现了ActionListener 接口。 通过上面的例子,你也许看出来了Java Swing/AWT包中窗口、控件的响应方式是一种源-监听器(Source/Listener)模式,也叫做观察者模式,这种机制常称为事件机制。

事件机制与消息机制的区别

Windows API可以开发窗口(界面)程序,Java通过Swing/AWT包也可以开发窗口(界面)程序,那么他们之间有什么异同呢? 1. 实现方式不同,Windows API主要是通过回调,提供对外的接口由用户去实现对应的处理,内部由操作系统实现,我们看不到;Java中的Swing/AWT主要源-监听器(观察者)模式,实现窗口(控件)对象与事件处理对象的邦定。 2. Windows API的消息机制有一个消息循环一直在接收消息,它是线程阻塞的。而Java的的Swing/AWT是一个通知方式,只有窗口(控件)有变化(被鼠标、键盘等触发)时才会通知监听者去处理,是非阻塞的。 3. 相同点:都有消息源——窗口(控件),都有消息处理,Windows API是窗口处理函数,Java中是监听者的处理方法,都有消息(Java叫事件Event)。如果把Windows API中消息队列和消息循环去掉,两者就很像了,就如同使用SendMessage直接把消息发送到窗口处理函数。所以,事件机制也可以认为是特殊的消息机制。

既然Java中的窗口程序是通过源-监听器(观察者)模式实现的,我们就有必要讨论一下观察者模式了。

观察者模式

观察者模式,顾名思意就是观察与被观察的关系,比如你在烧开水得时时看着它开没开,你就是观察者,开水就是被观察者;再比如说你在带小孩,你关注她是不是饿了,是不是喝了,是不是撒尿了,你就是观察者,小孩就被观察者。观察者模式是对象的行为模式,又叫发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。当你看这些模式的时候,不要觉得陌生,它们就是观察者模式。

观察者模式一般是一种一对多的关系,可以有任意个(一个或多个)观察者对象同时监听某一个对象。监听的对象叫观察者(后面提到监听者,其实就指观察者,两者是等价的),,被监听的对象叫被观察者(Observable,也叫主题Subject)。被观察者对象在状态上发生变化时,会通知所有观察者对象,使它们能够做出相应的变化(如自动更新自己的信息)。 我们就以上面提到的烧开水的一个简单生活实例来模拟一下观察者模式。 代码ObserverModule.java:

//人,观察者class Person {(String data) {System.out.println(data + “关电源…”);}}//水,被观察者class Water {private Person person;private boolean isBoiled;public Water() {isBoiled = false;}() {isBoiled = true;notifyObserve();}(Person person) {this.person = person;}() {if (person != null) {person = null;}}() {if (isBoiled && person != null) {person.update(“水开了,”);isBoiled = false;}}}ObserverModule {(String args[]) {Person person = new Person();Water water = new Water();water.addObserver(person);water.SetBoiled();}}

结果如下:

水开了,关电源…

却又小到连一粒嫉妒的沙石也不能容纳

java:从消息机制谈到观察者模式

相关文章:

你感兴趣的文章:

标签云: