디자인패턴) 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<String, String> students){
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<Observer> observers = 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<String, String> students;
public StudentData(){
students = new HashMap<>();
}
public void addStudent(String name, String number){
this.students.put(name, number);
notifyObservers(); //옵저버들에게 통보합니다.
}
public void removeStudent(String name){
this.students.remove(name);
notifyObservers(); //옵저버들에게 통보합니다.
}
public Map<String, String> getStudents(){
return this.students;
}
}
public class main {
public static void main(String[] args) throws 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를 추가적으로 작성하면 됩니다.
댓글
댓글 쓰기