观察者模式中的推模式与拉模式

来源:互联网 发布:怎么联系网络水军 编辑:程序博客网 时间:2024/05/03 03:51

观察者模式中的推模式与拉模式[摘录]

在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 AwtButtonextends 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 MyActionListenerimplements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("button pressed!");
        }
    }
    class MyActionListener1implements 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 MyActionListener1implements ActionListener {
    @Override
    public void actionPerform(ActionEvent e) {
        System.out.println("SimulationButton ActionPerformed:" +e.getTime() + e.getSource());
    }
}
class MyActionListener2implements 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 
本文版权归作者、博客园和百度空间共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则作者会诅咒你的。
如果您阅读了我的文章并觉得有价值请点击此处,谢谢您的肯定。
原创粉丝点击