傍観者モード

39741 ワード


いわゆる傍観者モード

observerは観察者の意味です.すなわち、傍観者モードは観察者モードであり、観察対象の状態が変化するか否かを観察する.

こうぞう


状態を変えることができるデータオブジェクトがあり,状態の変化を観察する傍観者オブジェクトがある.
普通のインタフェースで作っていますが、もっと分かりやすいようにクラスで表現したいと思います.
コードを表示する前に、まず、Subjectクラスを作成して、観測者に情報が変化したメッセージを送信し、Observerクラスを作成してメッセージを受信します.
import java.util.ArrayList;
import java.util.List;

public class Subject {

    private final List<Observer> observers;

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

    public void addObserver(Observer observer) {
        observers.add(observer);
        System.out.println(observer.getName() + " 추가");
    }

    public void removeObserver(Observer observer) {
        observers.remove(observer);
        System.out.println(observer.getName() + " 제거");
    }

    public void notify(String message) {
        for (Observer observer : observers) {
            observer.update(message);
        }
        System.out.println("메시지 전파 완료 : " + message);
    }
}
public class Observer {

    private final String name;

    public Observer(String name) {
        this.name = name;
    }

    void update(String message) {
        System.out.println(name + " : " + message + " 수신");
    }

    public String getName() {
        return name;
    }
}
Subjectクラスは複数のObserverクラスを有し、notify()を介してObserverクラスに情報変化の情報を送信する.では、Observer毎にメッセージが受信され、それぞれが処理される.これらのクラスを直接使用しましょう.
public class Main {

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

        Observer observer0 = new Observer("옵저버 A");
        subject.addObserver(observer0);

        Observer observer1 = new Observer("옵저버 B");
        subject.addObserver(observer1);

        Observer observer2 = new Observer("옵저버 C");
        subject.addObserver(observer2);

        Observer observer3 = new Observer("옵저버 D");
        subject.addObserver(observer3);

        subject.notify("Hello world!");
    }
}
実行結果
옵저버 A 추가
옵저버 B 추가
옵저버 C 추가
옵저버 D 추가
옵저버 A : Hello world! 수신
옵저버 B : Hello world! 수신
옵저버 C : Hello world! 수신
옵저버 D : Hello world! 수신
메시지 전파 완료 : Hello world!
subjectオブジェクトに傍観者が追加され、登録されたすべての傍観者がメッセージを受信したメッセージが送信されます.

適用


ここまで読めば、傍観者モードがどのような仕組みなのかを感じることができます.クラスではなくインタフェースを使用して「真の」傍観者モードを実現しましょう.
public interface Subject {
    void addObserver(Observer observer);
    void removeObserver(Observer observer);
    void notify(String message);
    void notify(int message);
}
public interface Observer {
    void update(String message);
    void update(int message);
}
SubjectおよびObserverをインターフェースとする.int型message情報を処理するために、方法が追加された.これらのインタフェースを継承するクラスを実装します.
import java.util.ArrayList;
import java.util.List;

public class Clock implements Subject {

    private final List<Observer> observers;

    public Clock() {
        this.observers = new ArrayList<>();
    }

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

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

    @Override
    public void notify(String message) {
        // do nothing
    }

    @Override
    public void notify(int message) {
        for (Observer observer : observers) {
            observer.update(message);
        }
    }

    public void clock() {
        for (int time = 1; time <= 24; ++time) {
            notify(time);
        }
    }
}
Subjectを継承するクロッククラスが作成されました.clock()は、1時から24時まで1時間ごとに通知を送信する関数です.
import java.util.Objects;

public class Army implements Observer {

    private final String[] todos = new String[25];

    public Army() {
        todos[ 1] = "불침번 기상";
        todos[ 2] = "다음 번대 불침번 깨우기";
        todos[ 7] = "아침 점호";
        todos[ 8] = "아침 식사";
        todos[ 9] = "오전 일과 시작";
        todos[12] = "점심 식사";
        todos[13] = "오후 일과 시작";
        todos[17] = "체력 단련";
        todos[18] = "저녁 식사";
        todos[19] = "개인 정비";
        todos[20] = "청소";
        todos[21] = "저녁 점호";
        todos[22] = "취침";
    }

    @Override
    public void update(String message) {
        // do nothing
    }

    @Override
    public void update(int message) {
        if (Objects.isNull(todos[message]))
            return;
        System.out.println("군인 : " + message + "시 - " + todos[message]);
    }
}
Observerを継承するArmyクラスが作成されました.軍人は1時間に1回時計を見て、時間通りに行動します.
実装されたコードを実行してみましょう.
import Army;
import Clock;

public class Main {

    public static void main(String[] args) {
        Clock clock = new Clock();

        Army army = new Army();
        clock.addObserver(army);

        clock.clock();
    }
}
実行結果
군인 : 1시 - 불침번 기상
군인 : 2시 - 다음 번대 불침번 깨우기
군인 : 7시 - 아침 점호
군인 : 8시 - 아침 식사
군인 : 9시 - 오전 일과 시작
군인 : 12시 - 점심 식사
군인 : 13시 - 오후 일과 시작
군인 : 17시 - 체력 단련
군인 : 18시 - 저녁 식사
군인 : 19시 - 개인 정비
군인 : 20시 - 청소
군인 : 21시 - 저녁 점호
군인 : 22시 - 취침
軍人のように、1時間ごとに時間を報告しなければならない.
今回は、Observerを継承する学生クラスを実現しましょう.
import java.util.Objects;

public class Student implements Observer {

    private final String[] todos = new String[25];

    public Student() {
        todos[ 7] = "기상";
        todos[ 8] = "식사";
        todos[ 9] = "1교시";
        todos[10] = "2교시";
        todos[11] = "3교시";
        todos[12] = "4교시";
        todos[13] = "점심 식사";
        todos[14] = "5교시";
        todos[15] = "6교시";
        todos[16] = "동아리 활동";
        todos[18] = "저녁 식사";
        todos[19] = "야간 자율 학습 시작";
        todos[22] = "야간 자율 학습 종료";
    }

    @Override
    public void update(String message) {
        // do nothing
    }

    @Override
    public void update(int message) {
        if (Objects.isNull(todos[message]))
            return;
        System.out.println("학생 : " + message + "시 - " + todos[message]);
    }
}
メイン関数からStudentクラスを呼び出すこともできます.
import Army;
import Clock;
import Student;

public class Main {

    public static void main(String[] args) {
        Clock clock = new Clock();

        Army army = new Army();
        clock.addObserver(army);
        Student student = new Student();
        clock.addObserver(student);

        clock.clock();
    }
}
実行結果
군인 : 1시 - 불침번 기상
군인 : 2시 - 다음 번대 불침번 깨우기
군인 : 7시 - 아침 점호
학생 : 7시 - 기상
군인 : 8시 - 아침 식사
학생 : 8시 - 식사
군인 : 9시 - 오전 일과 시작
학생 : 9시 - 1교시
학생 : 10시 - 2교시
학생 : 11시 - 3교시
군인 : 12시 - 점심 식사
학생 : 12시 - 4교시
군인 : 13시 - 오후 일과 시작
학생 : 13시 - 점심 식사
학생 : 14시 - 5교시
학생 : 15시 - 6교시
학생 : 16시 - 동아리 활동
군인 : 17시 - 체력 단련
군인 : 18시 - 저녁 식사
학생 : 18시 - 저녁 식사
군인 : 19시 - 개인 정비
학생 : 19시 - 야간 자율 학습 시작
군인 : 20시 - 청소
군인 : 21시 - 저녁 점호
군인 : 22시 - 취침
학생 : 22시 - 야간 자율 학습 종료
学生も軍人も1時間ごとに時計を見て、時間通りにそれぞれの仕事をすることができます.

おしゃべり

  • コードから見ると、clock.addObserver()クラス中のオブジェクトとArmyクラス中のオブジェクトは、Studentクラス中のオブジェクトとを直接無フォーマットに変換している.どちらもObserverの役割を果たしているクラスなので、形状変換などの操作がなくてもエラーは発生しません.
  • jdkはObservableクラスとObserverインタフェースを提供し、直接実施する必要がなく、使いやすい.