Observer와 Observable은 언제 사용해야합니까?


200

면접관이 나에게 물었다 :

무엇 ObserverObservable우리는 그것들을 언제 사용해야합니까?

나는 집으로 가지고와에 대해 인터넷 검색을 시작했다 그렇게 할 때, 이러한 용어를 인식하지이었다 Observer그리고 Observable, 내가 다른 자원에서 몇 가지 포인트를 발견 :

1) Observable클래스이며 Observer인터페이스입니다.

2) Observable클래스는의 목록을 유지합니다 Observer.

3) Observable객체가 업데이트되면 update()각 객체의 메소드를 호출하여 Observer변경되었음을 알립니다.

이 예를 찾았습니다.

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!");
    }
}

우리가 필요로하지만 왜 이해가 안 ObserverObservable? 의 방법 setChanged()notifyObservers(message)방법은 무엇입니까?


링크가 작동하지 않습니다. @Androider 업데이트 된 링크를 제공 할 수 있습니까?
prateek

Java 6 이상을 사용하는 경우이 dzone.com/articles/java-ee6-events-lightweight
Ramiz Uddin

1
디자인 패턴을 잘 이해하려면 이 책 을 읽어 보는 것이 좋습니다 . 그것은 바보처럼 나오지만 훌륭한 학습 도구입니다.
countofmontecristo

1
다들 참고하시기 바랍니다; Observer / Observable은 Java 9에서 더 이상 사용되지 않습니다. 대안 : stackoverflow.com/questions/46380073/…
eren130

답변:


265

학생과 메시지 게시판의 구체적인 예가 있습니다. 학생은 새 메시지가 MessageBoard에 게시 될 때 알림을받을 관찰자 목록에 자신을 추가하여 등록합니다. MessageBoard에 메시지가 추가되면 Observers 목록을 반복하여 이벤트가 발생했음을 알립니다.

트위터를 생각하십시오. 당신이 누군가를 따르고 싶다고 말하면, 트위터는 당신을 팔로어 목록에 추가합니다. 그들이 새 트윗을 보냈을 때 입력 한 내용을 볼 수 있습니다. 이 경우 Twitter 계정은 관찰자이며 팔로우하는 사람은 관찰자입니다.

트위터가 중재자 일 가능성이 높기 때문에 비유가 완벽하지 않을 수 있습니다. 그러나 그것은 요점을 보여줍니다.


57

매우 간단한 용어로 (다른 답변은 모든 공식 디자인 패턴을 참조하기 때문에 자세한 내용은 해당 패턴을 살펴보십시오).

프로그램 생태계의 다른 클래스에서 모니터링하는 클래스를 원한다면 클래스를 관찰 할 수 있다고 말합니다. 즉, 프로그램의 나머지 부분에 브로드 캐스트하려는 상태의 일부 변경 사항이있을 수 있습니다.

이제 이것을하기 위해서는 어떤 종류의 메소드를 호출해야합니다. 우리는 Observable 클래스가 그것을 관찰하고 싶은 클래스와 밀접하게 결합되는 것을 원하지 않습니다. 특정 기준을 충족하는 한 누구인지 신경 쓰지 않습니다. (이것이 라디오 방송국이라고 상상해보십시오. 주파수에 FM 라디오가 튜닝되어있는 한 누가 듣고 있는지 신경 쓰지 않습니다). 이를 위해 Observer라고하는 인터페이스를 사용합니다.

따라서 Observable 클래스에는 Observer 목록 (예 : 보유한 Observer 인터페이스 메서드를 구현하는 인스턴스)이 있습니다. 무언가를 방송하고 싶을 때마다 모든 관찰자에서 메소드를 하나씩 호출합니다.

퍼즐을 닫는 마지막 것은 Observable 클래스가 관심있는 사람을 어떻게 알 수 있는가입니다. 따라서 Observable 클래스는 관찰자가 자신의 관심을 등록 할 수있는 메커니즘을 제공해야합니다. addObserver(Observer o)내부적으로 옵저버를 옵저버 목록에 추가하는 것과 같은 메소드 는 중요한 일이 발생하면 목록을 반복하고 각 인스턴스의 옵저버 인터페이스에 대한 각 알림 메소드를 목록에서 호출합니다.

인터뷰에서 그들은 당신에게 java.util.Observer그리고 java.util.Observable일반적인 개념에 대해 명시 적으로 묻지 않았을 수도 있습니다 . 이 개념은 디자인 패턴이며, Java는 필요할 때 신속하게 구현할 수 있도록 즉시 지원을 제공합니다. 따라서 실제 메소드 / 클래스가 아니라 개념을 이해하는 것이 좋습니다 (필요할 때 찾아 볼 수 있음).

최신 정보

귀하의 의견에 따라 실제 java.util.Observable수업은 다음 시설을 제공합니다.

  1. java.util.Observer인스턴스 목록 유지 알림에 관심이있는 새로운 인스턴스는을 통해 추가하고을 통해 addObserver(Observer o)제거 할 수 있습니다 deleteObserver(Observer o).

  2. 관찰자에게 마지막 알림 이후에 개체가 변경되었는지 여부를 지정하여 내부 상태 유지 이는 Observable변경 사항을 알리는 부분과 변경 사항을 알리는 부분을 구분하기 때문에 유용합니다 . (예 : 여러 변경 사항이 발생하고 각 작은 단계가 아닌 프로세스가 끝날 때만 알리려는 경우에 유용합니다). 이것은를 통해 이루어집니다 setChanged(). 그래서 당신이 무언가를 바꿀 때 그것을 부르고 Observable나머지는 Observers결국 그것에 대해 알기 를 원합니다 .

  3. 모든 관찰자에게 특정 Observable상태가 변경 되었음을 알립니다 . 이것은를 통해 이루어집니다 notifyObservers(). 이것은 setChanged()알림을 진행하기 전에 객체가 실제로 변경되었는지 (즉, 호출되었는지) 확인합니다 . Object알림과 함께 추가 정보를 전달하려는 경우 인수가 없는 버전과 인수가있는 버전이 있습니다 . 내부적으로 일어나는 일은 Observer인스턴스 목록을 반복 update(Observable o, Object arg)하고 각 인스턴스에 대한 메소드를 호출한다는 것입니다. 이것은 Observer어느 Observable 객체가 변경되었고 (여러 개 이상을 관찰 할 수 있음), Object arg추가 정보를 전달할 여분의 정보를 알려줍니다 notifyObservers().


37

정의

관찰자 패턴은 하나의 오브젝트가 수정되고 종속 오브젝트에 자동으로 통지되고 모든 종속 오브젝트에 해당 변경이 수행되는 경우와 같이 오브젝트간에 일대 다 관계가있을 때 사용됩니다.

  1. 영구 주소가 변경되면 여권 당국과 팬 카드 당국에 알려야합니다. 그래서 여기 여권 당국과 팬 카드 당국은 관찰자이며 당신은 주제입니다.

  2. Facebook에서 또한 누군가를 구독하면 새 업데이트가 발생할 때마다 알림을받습니다.

사용시기 :

  1. 한 개체의 상태가 변경되면 일관성을 유지하기 위해 다른 모든 종속 개체가 자동으로 상태를 변경해야합니다

  2. 피험자가 보유한 관찰자 수를 모를 때

  3. 개체가 누구인지 모른 채 개체가 다른 개체에 알릴 수 있어야하는 경우

1 단계

주제 클래스를 작성하십시오.

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();
  }
}   

}

2 단계

관찰자 클래스를 작성하십시오.

Observer.java

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

3 단계

구체적인 관찰자 클래스 만들기

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 단계

피사체와 콘크리트 관찰자 객체를 사용하십시오.

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);
 }

}

5 단계

출력을 확인하십시오.

최초 상태 변경 : 15

16 진 문자열 : F

8 진 문자열 : 17

이진 문자열 : 1111

두 번째 상태 변경 : 10

16 진 문자열 : A

8 진 문자열 : 12

이진 문자열 : 1010


잘 :) 설명
roottraveller을

3
"정의"는 오타라고 생각합니다. 오타가 되길 바랍니다.
JohnJohn

10

이것은 관찰자 디자인 패턴의 일부입니다 . 일반적으로 하나 이상의 관찰자 에게 관찰 가능한 변경 사항에 대한 정보가 제공됩니다 . 프로그래머가 "무언가"의 의미를 정의 할 수있는 "무언가"가 발생했다는 알림입니다.

이 패턴을 사용할 때 두 엔티티를 서로 분리하면 관찰자가 플러그 가능하게됩니다.


board.changeMessage("More Homework!");답변에 설명을 추가 하면 changeMessage("More Homework!");호출 할 때 일어나는 일을 의미합니다 .
Ravi

9

관찰자 일명 콜백은 관찰 가능에 등록됩니다.

예를 들어 어떤 시점에서 발생한 이벤트에 대해 알리는 데 사용됩니다. UI 이벤트 (버튼 클릭, 텍스트 필드 변경 등)에 대한 작업을 디스패치하기 위해 Swing, Ajax, GWT에서 널리 사용됩니다.

Swing에는 addXXXListener (Listener l)와 같은 메소드가 있으며 GWT에는 (Async) 콜백이 있습니다.

관찰자 목록은 동적이므로 관찰자는 런타임 중에 등록 및 등록 취소 할 수 있습니다. 또한 인터페이스가 사용되므로 관찰자와 관찰자를 분리하는 좋은 방법입니다.


9

면접관이 Observer 클래스와 인터페이스를 사용하지 않고 Observer 디자인 패턴 을 구현하도록 요청 하면 다음과 같은 간단한 예제를 사용할 수 있습니다!

옵저버 인터페이스로서의 MyObserver

interface MyObserver {

    void update(MyObservable o, Object arg);
}

관찰 가능 클래스로 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 및 MyObservable을 사용한 예!

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

"왜 정확히 관찰자와 관찰이 필요한지 알아 내려고했습니다."

이전 답변에서 이미 언급했듯이 관찰자는 옵저버 블을 자동으로 수신하도록 옵저버를 구독하는 수단을 제공합니다.

이것이 유용한 응용 프로그램의 한 예는 데이터 바인딩 에 있습니다. 데이터 를 편집하는 UI가 있고 데이터가 업데이트 될 때 UI가 반응하고 데이터를 관찰 가능하게 만들고 UI 구성 요소를 구독한다고 가정 해 봅시다. 자료

Knockout.js는 MVVM 자바 스크립트 프레임 워크로 자습서를 시작하는 것이 더 좋습니다. http://learn.knockoutjs.com/

또한 Visual Studio 2008 시작 페이지에서이 기사를 찾았습니다 ( Observer 패턴은 MVC (Model View Controller) 개발의 기초입니다 ). http://visualstudiomagazine.com/articles/2013/08/14/the-observer-pattern-in -net.aspx


3

관찰자 패턴에 대한 간단한 설명을 여기에 작성했습니다. http://www.devcodenote.com/2015/04/design-patterns-observer-pattern.html

게시물의 스 니펫 :

관찰자 패턴 : 본질적으로 객체 사이의 일대 다 관계를 설정하고 상호 의존적 인 객체 사이에 느슨하게 결합 된 디자인을 갖습니다.

교과서 정의 : 관찰자 패턴은 객체 간의 일대 다 종속성을 정의하여 하나의 객체가 상태를 변경할 때 모든 종속 항목이 자동으로 통지되고 업데이트되도록합니다.

예를 들어 피드 알림 서비스를 고려하십시오. 구독자 모델은 관찰자 패턴을 이해하는 것이 가장 좋습니다.


0

관찰자 패턴은 하나의 오브젝트가 수정되는 경우 오브젝트간에 일대 다 관계가있을 때 사용되며 종속 오브젝트에 자동으로 통지됩니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.