观察者模式中的推模式与拉模式[摘录]
在Observer模式中区分推模式和拉模式,先简单的解释一下两者的区别:推模式是当有消息时,把消息信息以参数的形式传递(推)给所有观察者,而拉模式是当有消息时,通知消息的方法本身并不带任何的参数,是由观察者自己到主体对象那儿取回(拉)消息。知道了这一点,大家可能很容易发现上面我所举的例子其实是一种推模式的Observer模式。我们先看看这种模式带来了什么好处:当有消息时,所有的观察者都会直接得到全部的消息,并进行相应的处理程序,与主体对象没什么关系,两者之间的关系是一种松散耦合。但是它也有缺陷,第一是所有的观察者得到的消息是一样的,也许有些信息对某个观察者来说根本就用不上,也就是观察者不能“按需所取”;第二,当通知消息的参数有变化时,所有的观察者对象都要变化。鉴于以上问题,拉模式就应运而生了,它是由观察者自己主动去取消息,需要什么信息,就可以取什么,不会像推模式那样得到所有的消息参数。OK,说到这儿,你是否对于推模式和拉模式有了一点了解呢?
实际上上面的代码中,因java中awt事件的影响,我在Event中加入了source字段,这算是拉模式的一种体现。我们可以得到公共的事件信息,也可以通过source得到发出事件对象的信息。
AWT事件模拟
说到AWT事件,我们根据上面的思路模拟下awt事件处理,观察者模式实现awt事件功能更加简单优雅,然而真正的awt也需要windows本身的事件驱动的支持,比如你按下某个button,首先windows捕获这个消息,把消息分发给java虚拟机,虚拟机在调用button相应的处理,button调用监听器处理(个人理解)。一般awt事件处理:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
public
class
AwtButton
extends
Frame {
public
void
lanch() {
Button b =
new
Button(
"test"
);
b.addActionListener(
new
MyActionListener());
b.addActionListener(
new
MyActionListener1());
this
.add(b);
this
.addWindowListener(
new
WindowAdapter() {
@Override
public
void
windowClosing(WindowEvent e) {
System.exit(
0
);
}
});
setSize(
100
,
100
);
setVisible(
true
);
}
public
static
void
main(String[] args) {
new
AwtButton().lanch();
}
class
MyActionListener
implements
ActionListener {
@Override
public
void
actionPerformed(ActionEvent e) {
System.out.println(
"button pressed!"
);
}
}
class
MyActionListener1
implements
ActionListener {
@Override
public
void
actionPerformed(ActionEvent e) {
System.out.println(
"button pressed1!"
);
}
}
}
|
结合上面的孩子的例子,我们使用控制台模拟awt事件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
public
class
SimulationAwtButton {
public
static
void
main(String[] args) {
Button b =
new
Button();
b.addActionListener(
new
MyActionListener1());
b.addActionListener(
new
MyActionListener2());
b.pressed();
}
}
class
Button {
private
List<ActionListener> list =
new
ArrayList<ActionListener>();
public
void
addActionListener(ActionListener l) {
list.add(l);
}
public
void
pressed() {
ActionEvent e =
new
ActionEvent(
this
);
for
(ActionListener l : list) {
l.actionPerform(e);
}
}
}
interface
ActionListener {
void
actionPerform(ActionEvent e) ;
}
class
ActionEvent {
private
long
time;
private
Object source;
public
ActionEvent(Object source) {
this
.time = System.currentTimeMillis();
this
.source = source;
}
public
long
getTime() {
return
time;
}
public
Object getSource() {
return
source;
}
}
class
MyActionListener1
implements
ActionListener {
@Override
public
void
actionPerform(ActionEvent e) {
System.out.println(
"SimulationButton ActionPerformed:"
+e.getTime() + e.getSource());
}
}
class
MyActionListener2
implements
ActionListener {
@Override
public
void
actionPerform(ActionEvent e) {
System.out.println(
"SimulationButton ActionPerformed:"
+e.getTime() + e.getSource());
}
}
|
这样,对java送awt事件处理有了更深的认识。
适用性
1.当一个抽象模型有两个方面, 其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。
2.当对一个对象的改变需要同时改变其它对象, 而不知道具体有多少对象有待改变。
3.当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之, 你不希望这些对象是紧密耦合的。
总结
通过Observer模式,把一对多对象之间的通知依赖关系的变得更为松散,大大地提高了程序的可维护性和可扩展性,也很好的符合了开放-封闭原则。
参考资料
.NET设计模式(19):观察者模式(Observer Pattern)(部分摘录原文)
java尚学堂马士兵设计模式
作者: syxChina
出处: http://syxchina.cnblogs.com、 http://hi.baidu.com/syxcs123
本文版权归作者、博客园和百度空间共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则作者会诅咒你的。
如果您阅读了我的文章并觉得有价值请点击此处,谢谢您的肯定。