디자인패턴) ObserverPattern with Java

  • 데이터의 변경이 발생했을 때 데이터와 관련된 상대 클래스 혹은 객체에 의존하지 않고 데이터 변경을 통보하고자할 때 사용됩니다.
  •  








    • Subject에서는 통보 대상 객체들(Observers)을 관리합니다.
    • Subject를 상속받은 구현체(ConcreteSubject)는 통보 대상 객체들(Observers)에 대한 의존성없이 data가 변경 시 상대 객체들에게 통보가 가능합니다.
    • Observer의 각 구현체(ConcreteObserver)들은 통보 받을 시 작동하는 update() 메서드를 정의 합니다.
    • ConcreteSubject의 데이터를 참조하여 가공하려는 새로운 객체를 생성 시 기존의 코드 수정없이 추가적으로 작성이 가능하게 됩니다.

  • 옵저버 패턴을 이용하여 이름과 전화번호를 저장 및 삭제하고 출력하는 프로그램을 예시로 들어보겠습니다.















public interface Observer {
    public void update();
}

public class DataSheetView implements Observer {
    private StudentData studentData;
    
    public DataSheetView(StudentData studentData){
        this.studentData = studentData;
    }

    public void showStudents(Map<StringStringstudents){
        for(String key : students.keySet()){
            System.out.println(key + " : " + students.get(key));
        } 
    }

    @Override
    public void update() {
        showStudents(this.studentData.getStudents());
    }
}

public abstract class Subject {
    protected ArrayList<Observerobservers = new ArrayList<Observer>();

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

    public void detach(Observer observer){
        this.observers.remove(observer);
    }

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

public class StudentData extends Subject {
    private Map<StringStringstudents;

    public StudentData(){
        students = new HashMap<>();
    }

    public void addStudent(String nameString number){
        this.students.put(namenumber);
        notifyObservers(); //옵저버들에게 통보합니다.
    }

    public void removeStudent(String name){
        this.students.remove(name);
        notifyObservers(); //옵저버들에게 통보합니다.
    }
    
    public Map<StringStringgetStudents(){
        return this.students;
    }
}

public class main {
    public static void main(String[] argsthrows IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        
        StudentData studentData = new StudentData();
        DataSheetView dsv = new DataSheetView(studentData);
        studentData.attach(dsv);

        while(true){ 
            System.out.print("입력(이름 번호) : ");
            String str = br.readLine(); //이름과 번호를 입력하면 추가하는 기능입니다.
            StringTokenizer st = new StringTokenizer(str);
            //StringTokenizer는 기본적으로 공백을 기준으로 string들을 구분하여줍니다.
            studentData.addStudent(st.nextToken(), st.nextToken());
            System.out.println("------------------------------");
        }
}

 - 결과










데이터를 추가하는 기능만 실행해도 데이터가 변경되면서 출력하는 클래스에게 통보가 되어 출력 기능 까지 수행하는 것을 볼 수 있습니다.
더많은 기능이 필요하다면 observer를 추가적으로 작성하면 됩니다.

댓글

가장 많이 본 글