티스토리 뷰
Observer Pattern
- 옵저버 패턴은 객체의 상태 변화를 관찰하는 관찰자들, 즉 옵저버들의 목록을 객체에 등록하고 상태의 변화가 있을 때 마다 메서드 등을 통해 객체가 직접 목록의 각 옵저버에게 통지하도록 하는 패턴이다.
- 정리하면 변화가 발생될 것이 예상되는 객체에 옵저버를 보내놓고 변화가 일어나면 옵저버들을 통해 알림을 보내는 것이다.
다이어그램
Main.java 코드
public class MainWindow extends FrameWindow implements ActionListener, Subject {
// 생략
private static final ArrayList<Observer> observers = new ArrayList<>();
private PrimeObservableThread primeThread;
private TextFieldWindow textFieldWindow;
private LabelWindow labelWindow;
public MainWindow() {
}
public MainWindow(String title) {
super(title, X, Y, WIDTH, HEIGHT);
textFieldWindow = new TextFieldWindow(TEXT_FIELD_WINDOW_TITLE, X, Y + HEIGHT + GAP, WIDTH, HEIGHT);
labelWindow = new LabelWindow(LABEL_WINDOW_TITLE, X, Y + (HEIGHT + GAP) * 2, WIDTH, HEIGHT);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
primeThread.stopRunning();
textFieldWindow.closeWindow();
labelWindow.closeWindow();
System.exit(0);
}
});
// 옵저버들을 붙인 클래스들을 구독한다.
subscribe(textFieldWindow);
subscribe(labelWindow);
primeThread = new PrimeObservableThread();
primeThread.run();
}
public JPanel createPanel(int width, int height) {
/*
판넬 생성 코드
*/
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == updateTextFieldObserverButton) {
// start 버튼 누르면 해당 window 옵저버 구독
if (updateTextFieldObserverButton.getText().equals(START_TEXT_FIELD)) {
subscribe(textFieldWindow);
updateTextFieldObserverButton.setText(STOP_TEXT_FIELD);
} else {
// stop 구독 취소
unSubscribe(textFieldWindow);
updateTextFieldObserverButton.setText(START_TEXT_FIELD);
}
} else if (e.getSource() == updateLabelObserverButton) {
// start 버튼 누르면 해당 window 옵저버 구독
if (updateLabelObserverButton.getText().equals(START_LABEL_FIELD)) {
subscribe(labelWindow);
updateLabelObserverButton.setText(STOP_LABEL_FIELD);
} else {
// stop 구독 취소
unSubscribe(labelWindow);
updateLabelObserverButton.setText(START_LABEL_FIELD);
}
} else if (e.getSource() == stopButton) {
primeThread.stopRunning();
}
}
private JButton createButton(String text, ActionListener listener, int width, int height) {
/*
버튼 생성 로직
*/
}
public static void main(String[] args) {
new MainWindow(MainWindow.MAIN_TITLE);
}
@Override
public void subscribe(Observer observer) {
observers.add(observer);
}
@Override
public void unSubscribe(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyWindow(String msg) {
observers.forEach(observer -> observer.update(msg));
}
}
Subject 인터페이스
public interface Subject {
void subscribe(Observer observer);
void unSubscribe(Observer observer);
void notifyWindow(String msg);
}
Observer 인터페이스
public interface Observer {
void update(String msg);
}
LableWindow 클래스
public class LabelWindow extends FrameWindow implements Observer {
private JLabel label;
public LabelWindow(String title, int x, int y, int width, int height) {
super(title, x, y, width, height);
}
@Override
public void update(String msg) {
label.setText(msg);
label.validate();
}
public JPanel createPanel(int width, int height) {
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
label = new JLabel();
panel.add(label);
panel.setPreferredSize(new Dimension(width, height));
return panel;
}
}
TextFieldWindow 클래스
public class TextFieldWindow extends FrameWindow implements Observer {
private JTextField textField;
public TextFieldWindow(String title, int x, int y, int width, int height) {
super(title, x, y, width, height);
}
@Override
public void update(String msg) {
textField.setText(msg);
textField.validate();
}
public JPanel createPanel(int width, int height) {
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
textField = new JTextField();
panel.add(textField);
panel.setPreferredSize(new Dimension(width, height));
return panel;
}
}
PrimeObservableThread 클래스
// ~ 소수 생성 코드 ~
설명
- MainWindow 클래스에서 창을 생성한다. 이때 구독/취소를 위한 버튼창 & TextFieldWindow & LableWindow 세개의 창이 생긴다.
또한 Subject 인터페이스를 상속받아서 옵저버를 등록하고 취소하고 통보하는 구현을 한다. - Lable과 TextField클래스는 Observer 인터페이스를 상속받아서 옵저버가 붙게 된다.
- 소수 생성기인 PrimeObserableThread클래스에서 소수를 생성하고 옵저버에게 통보를 한다.
로직
- Observer를 상태 변화를 감시할 LableWindow와 TextFieldWindow에 붙여놓는다.
- 해당 옵저버를 구독한다.
- 소수를 계속 생성하고 이를 생성할 때 마다 notifyWindow()를 통해 TextFieldWindow와 LableWindow에 통보한다.
- 통보를 받은 두 윈도우는 update()를 수행한다.
- stop 버튼을 누르면 옵저버를 제거해서 더이상 변화를 통보받지 않는다. 다시 start 버튼을 누르면 다시 변화를 통보받게 된다.
- 이후 변화가 감지되면 notifyWindow()를 통해 변화를 옵저버들에게 통보한다.
결과
- start를 누르면 구독 : 소수가 생성되는 통보를 계속 받고 화면에 나타낸다.
- stop을 누르면 구독취소 : 더이상 화면의 소수를 업데이트하지 않는다.
반응형
'CS > GoF의 Design Pattern 정리' 카테고리의 다른 글
디자인 패턴 정리 - Singleton Pattern (0) | 2021.11.19 |
---|---|
디자인 패턴 정리 - Factory Method Pattern (0) | 2021.11.19 |
디자인 패턴 정리 - Decorator Pattern (0) | 2021.11.19 |
디자인 패턴 정리 - Strategy Pattern (0) | 2021.11.19 |
디자인 패턴 정리 - Polymorphism (0) | 2021.11.19 |
Comments
반응형
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday