Observerモード


Observerモードの例


オブジェクトのステータスが変更されると、他のオブジェクトが変更されたことを示す場合があります.
ステータスを持つボディオブジェクトと、ステータスの変更を知る必要があるオブジェクトが存在します.これらの関係は、1:1であってもよいし、1:Nであってもよい.
相互に情報を伝達し受信する過程で,情報の単位が大きいほどオブジェクトの規模が大きくなり,オブジェクト間の関係が複雑になるほど実現しにくくなり,複雑さも大きくなる.이러한 기능을 할 수 있도록 가이드라인을 제시해 주는것이 바로 옵저버 패턴입니다.具体的な例は,毎日ニュース番組が新しいニュースを提供していると仮定する.このプログラムは新しいニュースを収集し、情報を持っています.次に、このニュースプログラムからのニュースを購読するObserverを定義します.ニュースプログラムが新しいニュースを生成すると、すぐにこのメッセージを受け取ることができます.
これには、New ProgramというオブジェクトとObserverというオブジェクトが必要です.
これらのオブジェクトのクラスを設計する場合は、インタフェースを使用するオブジェクト間の分散結合を推奨します.これは、AにBがあり、通常、オブジェクトを1つのオブジェクトに含めるのではなく、インタフェースを使用することを意味します.
我々が使用するファイバモードでは,インタフェースもこのように利用する.主に2つの役割があります.1つはPublisherのキャラクターで、もう1つはObserverのキャラクターです.まずインタフェースを定義し、実装クラスを使用します.Publisherを実施する新しいプログラムクラスは、情報を提供するPublisherとなり、Observerのオブジェクトを有する.さらに、Observerインタフェースを実装するAnnualSubscriber(毎年の加入者)およびEventSubscriber(イベントクライアント)クラスは、新しいマシンがNotifyObserver()通知を呼び出すときに更新を呼び出す.これに基づいてJavaコードを作成しましょう.

Observerインタフェースの定義

public interface Observer {
    public void update(String title, String news);
}

Publisherインタフェースの定義


public interface Publisher {
    public void add(Observer observer);
    public void delete(Observer observer);
    public void notifyObserver();
}

New Machineクラス

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

public class NewsProgram implements Publisher {

    private List<Observer> observers;
    private String title;
    private String news;


    public NewsProgram() {
        observers = new ArrayList<>();
    }

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

    @Override
    public void delete(Observer observer) {
        int index = observers.indexOf(observer);
        observers.remove(index);
    }

    @Override
    public void notifyObserver() {
        for (Observer observer : observers){
            observer.update(title, news);
        }
    }

    public void setNewsInfo(String title, String news){
        this.title = title;
        this.news = news;
        notifyObserver();
    }

    public String getTitle() {
        return title;
    }

    public String getNews() {
        return news;
    }
}

AnnualSubscriberクラスの定義

public class AnnualSubscriber implements Observer {

    private String newsString;
    private Publisher publisher;

    public AnnualSubscriber(Publisher publisher) {
        this.publisher = publisher;
        publisher.add(this);
    }

    @Override
    public void update(String title, String news) {
        this.newsString = title + "\n----------\n " + news;
        display();
    }

    private void display(){
        System.out.println("\n\n오늘의 뉴스\n=================================\n\n" + newsString);
    }

    public void withdraw(){
        publisher.delete(this);
    }
}

EventSubscriberクラスの定義

public class EventSubscriber implements Observer {

    private String newsString;
    private Publisher publisher;

    public EventSubscriber(Publisher publisher) {
        this.publisher = publisher;
        publisher.add(this);
    }


    @Override
    public void update(String title, String news) {
        newsString = title + "\n-----------------------------------------\n" + news;
        display();
    }


    private void display(){
        System.out.println("\n\n=== 이벤트 유저 ===");
        System.out.println("\n\n" + newsString);

    }
    
    
    public void withdraw(){
        publisher.delete(this);
    }
}
Observerアレイ例の構成部品を実装した.メインクラスで実行しましょう
public class MainClass {

    public static void main(String[] args) {
        NewsProgram newsProgram = new NewsProgram();
        AnnualSubscriber as = new AnnualSubscriber(newsProgram);
        EventSubscriber es = new EventSubscriber(newsProgram);

        newsProgram.setNewsInfo("명절 대축제", "설날 연휴가 곧 끝나갑니다.");
        newsProgram.setNewsInfo("화요일부터", "출근을 해야합니다.");
    }
}

実行結果



2つのニュースは、上記の実行結果に示すように、AnnualSubscriberオブジェクトとEventSubscriberオブジェクトにそれぞれよく渡されます.この2つのオブジェクトを作成すると、Publisherは
リスト<Observer>.
ここで、AnnualSubscriberオブジェクトとEventSubscriberオブジェクトがメンバー変数としてPublisherオブジェクトを持つのは、リスト<Observer>リストを終了するときにこのPublisher Referenceを使用すると便利であるためです.上のコードからEventSubscriberオブジェクトesインスタンスを終了すると、次のように変更できます.
public class EventSubscriber implements Observer {

    private String newsString;
    private Publisher publisher;

    public EventSubscriber(Publisher publisher) {
        this.publisher = publisher;
        publisher.add(this);
    }


    @Override
    public void update(String title, String news) {
        newsString = title + "\n-----------------------------------------\n" + news;
        display();
    }


    private void display(){
        System.out.println("\n\n=== 이벤트 유저 ===");
        System.out.println("\n\n" + newsString);

    }

    // 구독 취소 메소드
    public void withdraw(){
        publisher.delete(this);
    }
}


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

        NewsProgram newsProgram = new NewsProgram();
        AnnualSubscriber as = new AnnualSubscriber(newsProgram);
        EventSubscriber es = new EventSubscriber(newsProgram);


        newsProgram.setNewsInfo("명절 대축제", "설날 연휴가 곧 끝나갑니다.");
        // es 인스턴스 observer 목록에서 탈퇴
        EventSubscriber.withdraw();
        newsProgram.setNewsInfo("화요일부터", "출근을 해야합니다.");

    }
}

実行結果



実行画面では、EventSubscriberオブジェクトは、2番目のニュースからサブスクリプションから除外されます.Publisher에서 정보나 상태가 변경될 때마다 Observer에게 보내는 방식을 우리가 흔히 알고 있는 푸시(Push)と申します.
反対はObserver에서 정보가 필요할 때마다 Publisher에게 요청하는 방식을 풀(Pull)です