推,拉机制观察者模式

时间:2016-01-10 13:53:05

标签: design-patterns

目前我正在研究设计模式,我已经找到了一个部分,我很困惑观察者模式是使用推动机制还是利用拉动机制?

我已经阅读了不同的实现,无法确定哪一个是正确的。

此外,我想知道推模型对拉模型的三个直接优势。 我猜其中一个是推模型与拉模型耦合较少?

3 个答案:

答案 0 :(得分:14)

观察者模式详细(关注问题)

  • 定义:观察者模式定义了对象之间的一对多依赖关系,这样当一个对象更改状态时,其所有依赖关系都会自动得到通知和更新

  • 要关注的3件事

    1. 可观察对象 - 被观察的对象。
    2. 观察者对象 - 观察可观察对象的对象
    3. 通讯机制 - 拉动或推动机制
  

目前我正在研究设计模式,我已经找到了一个部分,我很困惑观察者模式是使用推动机制还是利用拉动机制?

混乱可能是因为你是文学名字 - 拉或推。

请注意,在这两种机制中,Observable对象始终有责任通知所有订阅的观察者,但不同之处在于观察者是否[Push->;]获得所需的确切数据或[Pull->它将数据包含在某个对象中(主要是Observable对象)&它必须从中提取所需的数据。

  • 推送 - >观察者直接获得所需数据
  • 拉 - > Observer获取包装在对象中的数据,并且需要提取该数据。
  

我已经阅读了不同的实现,无法确定哪一个是正确的。

这里不是纠正的问题,实际上两者在任何情况下都能正常工作。如果我们看到这两种机制的以下细节,那么它最适合于特定场景/情况,可以轻松分析。

  

此外,我想知道推模型对拉模型的三个直接优势。我猜其中一个是推模型与拉模型耦合较少?

我可能无法提供3个优势,但如果我能通过使用用例示例清楚地了解使用方法,请试试看:

  • 推送机制

    • 这纯粹是Observable的责任,Observer只需要确保他们在他们的更新方法中放置了所需的代码。
    • 优点
      • “推”模型的主要优点是观察者和主体之间的耦合较低。
        • 可观察的& Observer都是接口/抽象类,实际上是一个设计原则 - 接口或超类型的程序
    • 缺点
      • 灵活性较低:由于Observable需要将所需数据发送给Observer,如果我们说1000个观察者并且大多数观察者需要不同类型的数据,它就会变得混乱。
    • 用例
      • 当最多2-3种不同类型的观察者(不同类型意味着观察者需要不同的数据)或所有观察者需要相同类型的数据时,应该使用它。
      • 与银行中的令牌系统一样
        • 在这个所有观察者(不同的LED)中只需要一个通知更新的等待令牌号列表,因此与Pull机制相比,可以更好地实现这种方式。
  • 拉动机制

    • 在拉机制中,Observable有责任通知所有观察者某些事情已经发生了变化,但这次Observable共享了有变化的整个对象,一些观察者可能不需要完整的对象,所以观察者只需要从更新方法中的完整项目中提取所需的详细信息。
    • 优点
      • 这样做的好处是更灵活。
        • 每个观察者可以自行决定要查询的内容,而不依赖主题发送正确的(仅需要的)信息。
    • 缺点
      • 观察者必须知道有关主题的事情才能从共享的完整对象中查询正确的信息。
    • 用例
      • 当有超过2-3种不同类型的观察者时应该使用它(不同类型意味着观察者需要不同的数据)
      • 就像任何外汇汇率提供商为不同的投资银行发布外汇汇率一样
        • 在这里,有些银行只处理INR,有些银行只处理GBP等,因此与Push机制相比,应该使用Pull机制来实现。

<强>参考

答案 1 :(得分:0)

观察者模式使用推送,因为可观察对象将通知推送给其订阅者。

Push vs Pull(主要是在网上): 推送 - 服务器向客户端发送(推送)通知,这意味着它需要跟踪他们的地址(URI)或更一般的情况下他们的参考。

拉 - 客户端负责从服务器请求新数据。

该模式不仅适用于Web,而且遍布全部,例如桌面应用程序。

答案 2 :(得分:0)

这是一个示例代码,如上所述,该代码使用“ PULL”模式。观察者可以获取不同类型的数据(在这种情况下未实现)。

import java.io.*;
import java.util.*;

 interface Observer{
    public void update();
}

 interface Observable {
    public void notifyAll() throws Exception;
    public void notify(Observer o) throws Exception;
}
class Suscriber implements Observer {
    String id;
    Subject subject;
    boolean registered = false;
    Double data = 0.0;
    public Suscriber(String id,Subject sub){
        this.id = id;
        subject = sub;    

        subject.register(this);
        registered = true;
    }

    public void update() {
        if(registered){
            data = subject.getData();
        }
        display();
    }

    void display(){
        System.out.println("Suscriber:" + id + " updated");
        System.out.println("Current DATA: " + data);
    }
}
class Subject implements Observable{
    private List<Observer> observers = new ArrayList<Observer>();
    private Double data = 0.0;

    public void register(Observer o){
        observers.add(o);
    }
    public void unregister(Observer o){
        int i =    observers.indexOf(o);

        observers.remove(i);
    }

    public void notify(Observer o) throws Exception{
          o.update();
    }

    public void notifyAll() throws Exception {
        for(Observer o:observers)
          this.notify(o);
    }

    public void computeMetrics(){
        try{
        long bunch = System.currentTimeMillis()/2;
        data = data + new Double(bunch);
        this.notifyAll();
        }catch(Exception ex){
            ex.printStackTrace();
        }
    }

    public Double getData() {
        return this.data;
    }
}

class ObserverTestDrive {
    public static void main (String[] args) {

        Subject subject = new Subject();

        long transmission = 10000;

        Suscriber norths = new Suscriber("NorthStation",subject);
        Suscriber wests = new Suscriber("WestStation",subject);
        Suscriber souths = new Suscriber("SouthStation",subject);

        for(int i=0;i<transmission;i++)
            subject.computeMetrics();










    }
}