Ne zaman Gözlemci ve Gözlemlenebilir kullanmalıyız?


200

Bir görüşmeci sordu:

Nedir Observerve Observablebiz bunları ne zaman kullanmalıyım?

Bu terimlerin farkında değildim, bu yüzden eve döndüğümde ve Googling'e başladığımda Observerve Observablefarklı kaynaklardan bazı noktalar buldum:

1) Observablebir sınıf ve Observerbir arayüzdür.

2) ObservableSınıf bir Observers listesini tutar .

3) Bir Observablenesne güncellendiğinde, bunu bildirmek için update()her birinin yöntemini çağırır Observer, değiştirilir.

Bu örneği buldum:

import java.util.Observable;
import java.util.Observer;

class MessageBoard extends Observable
{
    public void changeMessage(String message) 
    {
        setChanged();
        notifyObservers(message);
    }
}

class Student implements Observer 
{
    @Override
    public void update(Observable o, Object arg) 
    {
        System.out.println("Message board changed: " + arg);
    }
}

public class MessageBoardTest 
{
    public static void main(String[] args) 
    {
        MessageBoard board = new MessageBoard();
        Student bob = new Student();
        Student joe = new Student();
        board.addObserver(bob);
        board.addObserver(joe);
        board.changeMessage("More Homework!");
    }
}

Ama neden ihtiyacımız olduğunu anlamıyorum Observerve Observable? Nelerdir setChanged()ve notifyObservers(message)yöntemler için?


Bağlantı çalışmıyor. @Androider Güncellenmiş bağlantı sağlayabilir misiniz?
prateek

Java 6 veya daha yeni bir sürüm
Ramiz Uddin

1
Tasarım kalıplarını iyi anlamak için bu kitabı okumanızı şiddetle tavsiye ederim . Aptalca olarak karşımıza çıkıyor, ama mükemmel bir öğrenme aracı.
countofmontecristo

1
Herkes lütfen unutmayın; Gözlemci / Gözlemlenebilir Java 9'da kullanımdan kaldırılmıştır. Alternatifler: stackoverflow.com/questions/46380073/…
eren130

Yanıtlar:


264

Somut bir Öğrenci ve Mesaj Panosu örneğiniz var. Öğrenci, MessageBoard'a yeni bir Mesaj gönderildiğinde bildirim almak isteyen Gözlemciler listesine kendisini ekleyerek kaydolur. MessageBoard'a bir Message eklendiğinde, Observers (Gözlemciler) listesi üzerinden yinelenir ve olayın gerçekleştiğini bildirir.

Twitter düşünün. Birini takip etmek istediğinizi söylediğinizde, Twitter sizi takipçi listesine ekler. Yeni bir tweet gönderdiklerinde, bunu girişinizde görürsünüz. Bu durumda, Twitter hesabınız Gözlemci ve takip ettiğiniz kişi Gözlemlenebilir.

Analoji mükemmel olmayabilir, çünkü Twitter'ın bir Arabulucu olma olasılığı daha yüksektir. Ama konuyu açıklıyor.


57

Çok basit bir ifadeyle (diğer cevaplar sizi yine de tüm resmi tasarım modellerine yönlendiriyor, bu yüzden daha fazla ayrıntı için onlara bakın):

Programınızın ekosistemindeki diğer sınıflar tarafından izlenen bir sınıfa sahip olmak istiyorsanız, sınıfın gözlemlenebilir olmasını istediğinizi söylersiniz. Yani, programın geri kalanına yayınlamak isteyebileceğiniz bazı değişiklikler olabilir.

Şimdi, bunu yapmak için bir çeşit yöntem çağırmalıyız. Gözlemlenebilir sınıfın, onu gözlemlemek isteyen sınıflarla sıkı bir şekilde birleştirilmesini istemiyoruz. Belirli kriterleri yerine getirdiği sürece kimin olduğu umurumda değil. (Bir radyo istasyonu olduğunu düşünün, frekanslarına ayarlanmış bir FM radyoya sahip oldukları sürece kimin dinlediğini umursamıyor). Bunu başarmak için Gözlemci olarak adlandırılan bir arayüz kullanıyoruz.

Bu nedenle, Gözlemlenebilir sınıfında bir Gözlemciler listesi bulunur (örneğin Gözlemci arabirimi yöntemlerini uygulayan örnekler olabilir). Ne zaman bir şey yayınlamak isterse, yöntemi tüm gözlemcilerde birbiri ardına çağırır.

Bulmacayı kapatmak için son şey Gözlemlenebilir sınıfın kimin ilgilendiğini nasıl bileceğidir? Dolayısıyla, Gözlemlenebilir sınıf, Gözlemcilerin çıkarlarını kaydetmelerine izin verecek bazı mekanizmalar sunmalıdır. addObserver(Observer o)Dahili gibi bir yöntem , Gözlemciyi gözlemciler listesine ekler, böylece önemli bir şey olduğunda, listede dolaşır ve listedeki her bir örneğin Gözlemci arabiriminin ilgili bildirim yöntemini çağırır.

Röportajda size açıkça java.util.Observerve java.util.Observablegenel kavram hakkında soru sormamış olabilirler . Kavram, Java'nın gerektiğinde hızlı bir şekilde uygulamanıza yardımcı olmak için kutudan çıkar çıkmaz doğrudan destek sağladığı bir tasarım deseni. Bu yüzden, gerçek yöntemler / sınıflar yerine (anlamanız gerektiğinde bulabileceğiniz) kavramı anlamanızı öneririm.

GÜNCELLEME

Yorumunuza yanıt olarak, gerçek java.util.Observablesınıf aşağıdaki olanakları sunar:

  1. java.util.ObserverÖrneklerin bir listesini tutmak . Bildirim almakla ilgilenen yeni örnekler üzerinden eklenebilir addObserver(Observer o)ve bu durumlar kaldırılabilir deleteObserver(Observer o).

  2. Dahili bir durumu korumak, gözlemcilere son bildirimden sonra nesnenin değişip değişmediğini belirtmek. Bu yararlıdır çünkü Observabledeğiştiğini söylediğiniz bölümü , değişiklikleri bildirdiğiniz bölümden ayırır . (Örn. Birden fazla değişiklik olması ve her bir küçük adımdan ziyade yalnızca işlemin sonunda bildirimde bulunmak istiyorsanız faydalıdır). Bu ile yapılır setChanged(). Yani sadece bir şeyi değiştirdiğinizde çağırırsınız Observableve geri kalanının Observerssonunda bunu bilmesini istersiniz .

  3. Tüm gözlemcilere belirli Observabledurumun değiştiğini bildirmek . Bu ile yapılır notifyObservers(). Bu setChanged(), bildirime devam etmeden önce nesnenin gerçekten değişip değişmediğini (yani bir çağrı yapıldı) kontrol eder. ObjectBildirim ile bazı ek bilgiler iletmek istemeniz durumunda, biri bağımsız değişken ve biri bağımsız değişken içeren 2 sürüm vardır . Dahili olarak, sadece Observerörnek listesi üzerinden yinelenmesi ve update(Observable o, Object arg)her biri için yöntemi çağırmasıdır . Bu, Observerhangisinin değişen Gözlemlenebilir nesne olduğunu (birden fazla gözlemliyor olabilirsiniz) ve Object argpotansiyel olarak bazı ekstra bilgileri (geçilen) taşımak için ekstra olanı belirtir notifyObservers().


37

Tanım

Gözlemci deseni, bir nesne değiştirilmişse, bağımlı nesneleri otomatik olarak bildirilecek ve tüm bağımlı nesnelere karşılık gelen değişiklikler yapılacak gibi nesneler arasında bire çok ilişki olduğunda kullanılır.

Örnekler

  1. Diyelim ki, kalıcı adresiniz değiştiğinde pasaport yetkilisini ve pan kartı yetkilisini bilgilendirmeniz gerekir. Yani burada pasaport otoritesi ve pan kartı otoritesi gözlemci ve sen bir öznesin.

  2. Facebook'ta da, birisine abone olursanız, her yeni güncelleme olduğunda size bildirilir.

Ne zaman kullanılır:

  1. Bir nesne durumunu değiştirdiğinde, diğer tüm bağımlı nesneler tutarlılığı korumak için durumlarını otomatik olarak değiştirmelidir

  2. Konu gözlemcilerin sayısını bilmiyorsa.

  3. Bir nesnenin, nesnelerin kim olduğunu bilmeden diğer nesneleri bilgilendirmesi gerektiğinde.

Aşama 1

Konu sınıfı oluşturun.

Subject.java

  import java.util.ArrayList;
  import java.util.List;

  public class Subject {

  private List<Observer> observers 
        = new ArrayList<Observer>();
  private int state;

  public int getState() {
    return state;
  }

 public void setState(int state) {
   this.state = state;
   notifyAllObservers();
 }

   public void attach(Observer observer){
     observers.add(observer);       
   }

  public void notifyAllObservers(){
    for (Observer observer : observers) {
     observer.update();
  }
}   

}

Adım 2

Observer sınıfı oluşturun.

Observer.java

public abstract class Observer {
   protected Subject subject;
   public abstract void update();
}

Aşama 3

Somut gözlemci sınıfları oluşturun

BinaryObserver.java

public class BinaryObserver extends Observer{

  public BinaryObserver(Subject subject){
     this.subject = subject;
     this.subject.attach(this);
  }

  @Override
  public void update() {
     System.out.println( "Binary String: " 
     + Integer.toBinaryString( subject.getState() ) ); 
  }

}

OctalObserver.java

public class OctalObserver extends Observer{

   public OctalObserver(Subject subject){
     this.subject = subject;
    this.subject.attach(this);
 }

  @Override
  public void update() {
    System.out.println( "Octal String: " 
    + Integer.toOctalString( subject.getState() ) ); 
  }

}

HexaObserver.java

public class HexaObserver extends Observer{

  public HexaObserver(Subject subject){
    this.subject = subject;
    this.subject.attach(this);
 }

  @Override
  public void update() {
     System.out.println( "Hex String: " 
    + Integer.toHexString( subject.getState() ).toUpperCase() ); 
}

}

4. Adım

Konu ve somut gözlemci nesneleri kullanın.

ObserverPatternDemo.java

 public class ObserverPatternDemo {
    public static void main(String[] args) {
       Subject subject = new Subject();

       new HexaObserver(subject);
       new OctalObserver(subject);
       new BinaryObserver(subject);

       System.out.println("First state change: 15");    
       subject.setState(15);
       System.out.println("Second state change: 10");   
       subject.setState(10);
 }

}

Adım 5

Çıktıyı doğrulayın.

İlk eyalet değişikliği: 15

Onaltılı Dize: F

Sekizli Dize: 17

İkili Dize: 1111

İkinci durum değişikliği: 10

Onaltılı Dize: A

Sekizli Dize: 12

İkili Dize: 1010


güzel açıkladı :)
roottraveller

3
"Tanımlama" bir yazım hatasıdır. Umarım bu bir yazım hatasıdır.
JohnJohn

10

Bunlar, Observer tasarım modelinin parçalarıdır . Genellikle bir veya daha fazla gözlemcilerini birinde değişiklikler hakkında bilgi almak gözlemlenebilir . Bir programcı olarak sizin "bir şeyin" ne anlama geldiğini tanımlayabileceğiniz "bir şeyin" gerçekleştiği bir bildiridir.

Bu deseni kullanırken, her iki objeyi birbirinden ayırırsınız - gözlemciler takılabilir hale gelir.


takdir edersiniz, board.changeMessage("More Homework!");cevabınıza açıklama ekleyecekseniz, changeMessage("More Homework!");çağrıldığında ne olur demek istiyorum .
Ravi

9

Gözlemci veya geri arama Gözlemlenebilir'e kaydedilir.

Örneğin, belirli bir zamanda meydana gelen olaylar hakkında bilgi vermek için kullanılır. Swing, Ajax, GWT'de, örneğin UI olayları (düğme tıklamaları, metin alanları değişti vb.)

Swing'de addXXXListener (Listener l) gibi yöntemler bulursunuz, GWT'de (Async) geri çağrılarınız vardır.

Gözlemcilerin listesi dinamik olduğundan gözlemciler çalışma sırasında kayıt olabilir ve kayıtlarını kaldırabilirler. Arayüzler kullanıldığından, gözlemcilerden gözlemlenebilir ayrıştırmanın iyi bir yoludur.


9

Görüşmeci, Observer sınıflarını ve arabirimlerini kullanmadan Observer tasarım modelini uygulamayı isterse , aşağıdaki basit örneği kullanabilirsiniz!

Gözlemci arayüzü olarak MyObserver

interface MyObserver {

    void update(MyObservable o, Object arg);
}

Gözlemlenebilir sınıf olarak MyObservable

class MyObservable
{
    ArrayList<MyObserver> myObserverList = new ArrayList<MyObserver>();

    boolean changeFlag = false;

    public void notifyObservers(Object o)
    {
        if (hasChanged())
        {
            for(MyObserver mo : myObserverList) {
                mo.update(this, o);
            }
            clearChanged();
        }
    }


    public void addObserver(MyObserver o) {
        myObserverList.add(o);        
    }

    public void setChanged() {
        changeFlag = true;
    }

    public boolean hasChanged() {
        return changeFlag;
    }

    protected void clearChanged() {
        changeFlag = false;
    }

    // ...
}

MyObserver ve MyObservable ile örnek!

class MessageBoard extends MyObservable {
  private String message;

  public String getMessage() {
    return message;
  }

  public void changeMessage(String message) {
    this.message = message;
    setChanged();
    notifyObservers(message);
  }

  public static void main(String[] args) {
    MessageBoard board = new MessageBoard();
    Student bob = new Student();
    Student joe = new Student();
    board.addObserver(bob);
    board.addObserver(joe);
    board.changeMessage("More Homework!");
  }
}

class Student implements MyObserver {

  @Override
  public void update(MyObservable o, Object arg) {
    System.out.println("Message board changed: " + arg);
  }

}

5

"Neden tam olarak Gözlemci ve Gözlemlenebilirliğe ihtiyacımız olduğunu anlamaya çalıştım"

Önceki yanıtların daha önce belirttiği gibi, bir gözlemciye, bir gözlemlenebilir kişinin otomatik bildirimlerini almak için abone olma yöntemleri sağlarlar.

Bunun yararlı olabileceği örnek bir uygulama veri bağlamadır , diyelim ki bazı verileri düzenleyen bazı kullanıcı arayüzünüz var ve veriler güncellendiğinde kullanıcı arayüzünün tepki vermesini istiyorsunuz, verilerinizi gözlenebilir hale getirebilir ve kullanıcı arayüzü bileşenlerinizi veri

Knockout.js harika bir başlangıç ​​öğreticisi olan bir MVVM javascript çerçevesidir, daha fazla gözlemlenebilir görmek için gerçekten öğreticiden geçmenizi tavsiye ederim. http://learn.knockoutjs.com/

Bu makaleyi ayrıca Visual Studio 2008 başlangıç ​​sayfasında da buldum ( Gözlemci Modeli, Model Görünüm Denetleyicisi (MVC) geliştirmenin temelidir ) http://visualstudiomagazine.com/articles/2013/08/14/the-observer-pattern-in -net.aspx


3

Burada gözlemci modelinin kısa bir açıklamasını yazdım: http://www.devcodenote.com/2015/04/design-patterns-observer-pattern.html

Gönderiden bir pasaj:

Gözlemci Deseni: Aslında nesneler arasında bire çok ilişki kurar ve birbirine bağlı nesneler arasında gevşek bir şekilde birleştirilmiş bir tasarıma sahiptir.

Ders Kitabı Tanımı: Gözlemci Deseni, nesneler arasında bire çok bağımlılık tanımlar, böylece bir nesne durumu değiştiğinde tüm bağımlıları otomatik olarak bildirilir ve güncellenir.

Örneğin, bir feed bildirim hizmetini düşünün. Abonelik modelleri, gözlemci modelini anlamak için en iyisidir.


0

Gözlemci deseni, bir nesne değiştirilmişse bağımlı nesneleri otomatik olarak bildirilecek gibi nesneler arasında bire çok ilişki olduğunda kullanılır.


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.