Observer Pattern(옵저버 패턴)이란?
Observer Pattern은 디자인 패턴(생성, 구조, 행동) 중 행동 디자인 패턴에 속한다.
주체가 어떤 객체(subject)의 상태 변화를 관찰 하다가 상태 변화가 있을 때마다 메서드 등을 통해 옵저버 목록에 있는 옵저버들에게 변화를 알려주는 디자인 패턴이다.
이런 변화를 알려주는 과정에서 흔히 객체가 발행자(publish) 옵저버가 구독자(subscribe)로도 알려져 있으며 이는 객체와 옵저버가 1:N관계를 가지며 분산 이벤트 시스템을 구현하는 데 이용하기도 한다.
물론 이렇게만 읽으면 크게 와닿는게 없다..!
그래도 저기서 bold처리한 객체와 옵저버가 존재하고 객체(subject)의 상태변화가 있을 때마다 옵저버가 알게되어야 하는 상황이라면 어떤 상황에서든 옵저버 패턴으로 설명이 가능하다.
객체(subject) = > 특정 정보를 발행하는 객체, 관찰 대상자
옵저버(Observer) => 특정 정보를 구독하는 객체, 관찰자
인터넷 구글링을 해보면 다른 많은 사람들이 날씨 어플 개발을 통한 예시(그 외에도 유투브 구독, 트위터 서비스 등등)로 설명해주시는게 많은데, 나는 내 생각을 더 정리하고자 내가 만들어낸 예시로 학습해보겠다.
예시
많은 예시가 있겠지만 나는 개를 키우는 견주로서 개와 주인들인 우리 가족으로 예시를 두겠다.
개를 객체(subject)로 두고 개의 상태(물을 다 마셨다. 밥을 다 먹었다. 똥을 쌌다 .. )등 상태 변화를 알고 싶은 주인(observer)들이 존재하는 상황을 생각해보자.

이때 개가 객체(subject)이고 우리가족들(엄마, 아빠, 나)가 옵저버(observer)이다.
그럼 대체 이 상황에서 옵저버 패턴을 어떻게 쓰고 언제 쓰는거고 왜 만들어졌을까?
자, 물음에 바로 답하기 전에 우선 디자인 패턴이 무엇인지 간단히 짚고 넘어가보자.
소프트웨어 개발에서의 디자인 패턴은 소프트웨어 개발의 일반적인 문제에 대한 해결책으로, 모든 프로그래밍 언어 및 업계의 개발자가 자주 직면하는 문제에 대한 해결책이다.
그럼 우리는 이 정의에서 언제 쓰는 지, 왜 만들어졌는 지에 대해서 두리뭉술하게 말할 수 있다.
어떠한 개발 과정에서 문제가 있었고 이 문제를 해결하기 위한 행동 디자인 패턴인 옵저버 패턴이 만들어졌고, 문제 상황을 옵저버 패턴으로 해결 할 수 있는 경우 그때 사용하면 되는 것이다.
그럼 이 Observer Pattern은 어떤 문제에 대한 해결책인지 어떻게 쓰는건지 예시코드와 함께 알아보자.
기존 개발에 대한 문제점( == Observer Pattern이 해결 할 수 있는 문제점)
내가 말했던 개의 상태 변화를 주인이 알고 싶을 때의 예제 코드는 다음과 같다.
public class Dog {
private String action;
public void eat() {
action = "밥을 다 먹었다.";
}
public void drink() {
action = "물을 다 마셨다.";
}
public void poop() {
action = "똥을 쌌다.";
}
public String getAction() {
return action;
}
}
public class Owner {
private String name;
public Owner(String name) {
this.name = name;
}
public void checkDogState(Dog dog) {
String action = dog.getAction();
System.out.println(name + "이(가) 강아지의 상태를 확인했습니다. 행동: " + action);
}
}
public class LegacyCodeExample {
public static void main(String[] args) {
Dog dog = new Dog();
Owner owner1 = new Owner("주인1");
Owner owner2 = new Owner("주인2");
// 상태 변화
dog.eat();
owner1.checkDogState(dog);
owner2.checkDogState(dog);
dog.drink();
owner1.checkDogState(dog);
owner2.checkDogState(dog);
owner1.checkDogState(dog);
owner2.checkDogState(dog);
dog.poop();
owner1.checkDogState(dog);
owner2.checkDogState(dog);
}
}
이 예제 코드에서는 강아지(Dog) 클래스의 상태 변화 메서드가 호출될 때마다 각 주인(Owner)이 직접 checkDogState 메서드를 호출하여 강아지의 상태를 확인할 수 있다. 그러나 이 방식은 주기적으로 상태를 조회하며 상태 변화를 감지하는 방법으로 비효율적이며 실시간으로 상태를 알리기 어렵다.
또한 다른 예시로는 다음과 같다.
public class Owner {
private String name;
private Dog dog; // Owner 클래스가 Dog 객체를 직접 참조
public Owner(String name, Dog dog) {
this.name = name;
this.dog = dog;
}
public void checkDogState() {
String action = dog.getAction();
System.out.println(name + "이(가) 강아지의 상태를 확인했습니다. 행동: " + action);
}
}
public class LegacyCodeExample {
public static void main(String[] args) {
Dog dog = new Dog();
Owner owner1 = new Owner("주인1", dog);
Owner owner2 = new Owner("주인2", dog);
// 상태 변화
dog.eat();
owner1.checkDogState();
dog.drink();
owner2.checkDogState();
dog.poop();
owner1.checkDogState();
}
}
이것은 옵저버 패턴의 장점을 설명하기 이전에 레거시에서의 안좋은 점을 부각하기 위해 추가한 예시이다.
Owner 클래스가 Dog 클래스를 직접적으로 참조하여 매우 강한 결합으로 되어있는 것을 확인 하면 된다.
Observer Pattern 구현 방법
observer pattern의 큰 틀은 다음과 같다.
인터페이스 Subject와 Observer를 설정하는 것이다.
Subject Interface
public interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers(String action);
}
subject의 인터페이스는 observer를 등록, observer 해지, 상태 변화를 observer들에게 알리는 메서드를 가지고 있는 것을 확인 할 수 있다.
Observer Interface
public interface Observer {
void update(String action);
}
observer 인터페이스는 관찰하고 있는 객체의 상태 변화(update)를 옵저버가 알 수 있는 메서드를 가지고 있다.
자 이제 이 인터페이스 두개가지고 똑같은 예시인 객체 Dog와 Owner를 구현해보자.
import java.util.ArrayList;
import java.util.List;
public class Dog implements Subject {
private List<Observer> observers = new ArrayList<>();
private String action;
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers(String action) {
for (Observer observer : observers) {
observer.update(action);
}
}
public void eat() {
action = "밥을 다 먹었다.";
notifyObservers(action);
}
public void drink() {
action = "물을 다 마셨다.";
notifyObservers(action);
}
public void poop() {
action = "똥을 쌌다.";
notifyObservers(action);
}
}
public class Owner implements Observer {
private String name;
public Owner(String name) {
this.name = name;
}
@Override
public void update(String action) {
System.out.println(name + "이(가) 강아지의 상태 변화를 감지했습니다. 행동: " + action);
}
}
public class ObserverPatternExample {
public static void main(String[] args) {
Dog dog = new Dog();
Owner owner1 = new Owner("주인1");
Owner owner2 = new Owner("주인2");
// 옵저버 등록
dog.registerObserver(owner1);
dog.registerObserver(owner2);
// 상태 변화
dog.eat();
dog.drink();
dog.poop();
}
}
옵저버 패턴을 적용한 이 예제 코드에서 확인 할 수 있다 시피,
이전 레거시 코드(문제가 되는 코드)와 달리 객체의 상태 변화가 있을 때 실시간으로 옵저버들에게 정보가 확인되는 구조이다.
즉, 알고 싶은 객체의 상태 변화를 별도의 함수 호출 없이 즉각적으로 알 수 있기 때문에 이벤트에 대한 처리를 자주해야 하는 프로그램이라면 매우 효율적인 프로그램을 작성할 수 있는 것이다.
Observer Pattern의 장단점
장점
1. Subject의 상태 변화를 주기적으로 조회하지 않아도 된다.
2. Subject와 Observer 객체 사이의 관계가 느슨하게 관리된다.
== Subject의 코드를 변경하지 않고도 새로운 Observer 클래스를 도입할 수 있어 개방 폐쇄 원칙(OCP) 준수한다
3. Runtime 시점에 Observer를 추가, 제거할 수 있다.
단점
1. Observer의 응답 순서를 보장하지 않는다.
2. Observer를 명시적으로 추가, 제거하기 때문에 메모리 누수가 발생할 가능성이 존재한다.
자바의 내장 옵저버 객체
자바에서 별도로 옵저버 패턴을 직접 구현하지 않아도 옵저버 패턴을 사용할 수 있도록 내장 옵저버 객체들이 존재한다.
1. Obserable과 Observer ( 자바 9버전 부터 deprecated가 되었다 )
2. PropertyChangeSuppoter와 PropertyChangeListener
java.util.Obserable

자바 9버전 부터는 deprecated가 되었다고 명시되어있고 여기서 확인할 점은 Observable은 class로 구현되어있어 후에 Dog와 같은 클래스를 구현하기 위해서는 extends를 사용하는것, Observer들을 Vector로 관리해 멀티 스레드 및 병렬처리에 안전하다는 점을 확인할 수 있다.
이 Observable으로 Dog를 구현해보면 다음과 같다.
import java.util.Observable;
public class Dog extends Observable {
private String action;
public void eat() {
action = "밥을 다 먹었다.";
this.setChanged();
this.notifyObservers(action);
}
public void drink() {
action = "물을 다 마셨다.";
this.setChanged();
this.notifyObservers(action);
}
public void poop() {
action = "똥을 쌌다.";
this.setChanged();
this.notifyObservers(action);
}
}
이 때 또 기존과 다른 점은 this.setChanged()로 변화를 알려줘야 notifyObservers()를 통해 이전과 같이 변화가 있을 때 알려주는것처럼 동작한다는 것이다.
java.util.Observer

마찬가지로 자바 9버전부터는 deprecated가 되었다.
import java.util.Observable;
import java.util.Observer;
public class Owner implements Observer {
private String name;
public Owner(String name) {
this.name = name;
}
@Override
public void update(Observable o, Object arg) {
if (o instanceof Dog) {
String action = (String) arg;
System.out.println(name + "이(가) 강아지의 상태 변화를 감지했습니다. 행동: " + action);
}
}
}
java.bean.PropertyChangeSuppoter

Observable처럼 클래스로 구현되어있는 것을 확인할 수있고 작게 thread-safe하다는 것도 확인할 수 있다.
또한 Observer 역할인 PropertyChangeLister들을 Map으로 관리하고 있는 모습이다.
그러나 이전에 상속이나 인터페이스 구현과 같은 방법이 아닌 이 PropertyChangeSupport를 필드로 두어 구현하는것이 다른 차이점 이다. 코드로 확인해보자.
public class Dog {
PropertyChangeSupport support = new PropertyChangeSupport(this);
private String action;
public void addObserver(PropertyChangeListener observer) {
if (observer != null) {
this.support.addPropertyChangeListener(observer);
}
}
public void removeObserver(PropertyChangeListener observer) {
if (observer != null) {
this.support.removePropertyChangeListener(observer);
}
}
public void notifyObservers(String newValue) {
support.firePropertyChange("event name", null, newValue);
}
public void eat() {
action = "밥을 다 먹었다.";
this.notifyObservers(action);
}
public void drink() {
action = "물을 다 마셨다.";
this.notifyObservers(action);
}
public void poop() {
action = "똥을 쌌다.";
this.notifyObservers(action);
}
}
java.bean.PropertyChangeListener

PropertyChangeListener는 인터페이스이고, 차이점은 PropertyChangeEvent인 객체로 달라진 상태(이벤트)를 확인 할 수 있다는 점이다.
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
public class Owner implements PropertyChangeListener {
private String name;
public Owner(String name) {
this.name = name;
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
System.out.println(name + "이(가) 강아지의 상태 변화를 감지했습니다. 행동: " + evt.getNewValue());
}
}
매번 디자인패턴 띡- 생성, 구조, 행동 그리고 무엇 무엇이 있고 정의에 대해서 겉으로만 읽을때와 달리
이렇게 하나의 내가 생각한 예제와 코드를 구현하니 옵저버 패턴에 대해서 조금 더 많이 학습하게 된 것 같다.
출처
'CS > 디자인패턴' 카테고리의 다른 글
[Design Pattern] Strategy Pattern(전략 패턴) (0) | 2024.06.02 |
---|---|
[Design Pattern] Factory Pattern(팩토리 패턴) (0) | 2024.06.01 |
[Design Pattern] Singleton Pattern(싱글톤 패턴) (0) | 2024.05.31 |
[Design Pattern] Builder Pattern(빌더 패턴) (1) | 2024.02.07 |
[Design Pattern] 디자인 패턴이란? (0) | 2024.01.23 |
Observer Pattern(옵저버 패턴)이란?
Observer Pattern은 디자인 패턴(생성, 구조, 행동) 중 행동 디자인 패턴에 속한다.
주체가 어떤 객체(subject)의 상태 변화를 관찰 하다가 상태 변화가 있을 때마다 메서드 등을 통해 옵저버 목록에 있는 옵저버들에게 변화를 알려주는 디자인 패턴이다.
이런 변화를 알려주는 과정에서 흔히 객체가 발행자(publish) 옵저버가 구독자(subscribe)로도 알려져 있으며 이는 객체와 옵저버가 1:N관계를 가지며 분산 이벤트 시스템을 구현하는 데 이용하기도 한다.
물론 이렇게만 읽으면 크게 와닿는게 없다..!
그래도 저기서 bold처리한 객체와 옵저버가 존재하고 객체(subject)의 상태변화가 있을 때마다 옵저버가 알게되어야 하는 상황이라면 어떤 상황에서든 옵저버 패턴으로 설명이 가능하다.
객체(subject) = > 특정 정보를 발행하는 객체, 관찰 대상자
옵저버(Observer) => 특정 정보를 구독하는 객체, 관찰자
인터넷 구글링을 해보면 다른 많은 사람들이 날씨 어플 개발을 통한 예시(그 외에도 유투브 구독, 트위터 서비스 등등)로 설명해주시는게 많은데, 나는 내 생각을 더 정리하고자 내가 만들어낸 예시로 학습해보겠다.
예시
많은 예시가 있겠지만 나는 개를 키우는 견주로서 개와 주인들인 우리 가족으로 예시를 두겠다.
개를 객체(subject)로 두고 개의 상태(물을 다 마셨다. 밥을 다 먹었다. 똥을 쌌다 .. )등 상태 변화를 알고 싶은 주인(observer)들이 존재하는 상황을 생각해보자.

이때 개가 객체(subject)이고 우리가족들(엄마, 아빠, 나)가 옵저버(observer)이다.
그럼 대체 이 상황에서 옵저버 패턴을 어떻게 쓰고 언제 쓰는거고 왜 만들어졌을까?
자, 물음에 바로 답하기 전에 우선 디자인 패턴이 무엇인지 간단히 짚고 넘어가보자.
소프트웨어 개발에서의 디자인 패턴은 소프트웨어 개발의 일반적인 문제에 대한 해결책으로, 모든 프로그래밍 언어 및 업계의 개발자가 자주 직면하는 문제에 대한 해결책이다.
그럼 우리는 이 정의에서 언제 쓰는 지, 왜 만들어졌는 지에 대해서 두리뭉술하게 말할 수 있다.
어떠한 개발 과정에서 문제가 있었고 이 문제를 해결하기 위한 행동 디자인 패턴인 옵저버 패턴이 만들어졌고, 문제 상황을 옵저버 패턴으로 해결 할 수 있는 경우 그때 사용하면 되는 것이다.
그럼 이 Observer Pattern은 어떤 문제에 대한 해결책인지 어떻게 쓰는건지 예시코드와 함께 알아보자.
기존 개발에 대한 문제점( == Observer Pattern이 해결 할 수 있는 문제점)
내가 말했던 개의 상태 변화를 주인이 알고 싶을 때의 예제 코드는 다음과 같다.
public class Dog {
private String action;
public void eat() {
action = "밥을 다 먹었다.";
}
public void drink() {
action = "물을 다 마셨다.";
}
public void poop() {
action = "똥을 쌌다.";
}
public String getAction() {
return action;
}
}
public class Owner {
private String name;
public Owner(String name) {
this.name = name;
}
public void checkDogState(Dog dog) {
String action = dog.getAction();
System.out.println(name + "이(가) 강아지의 상태를 확인했습니다. 행동: " + action);
}
}
public class LegacyCodeExample {
public static void main(String[] args) {
Dog dog = new Dog();
Owner owner1 = new Owner("주인1");
Owner owner2 = new Owner("주인2");
// 상태 변화
dog.eat();
owner1.checkDogState(dog);
owner2.checkDogState(dog);
dog.drink();
owner1.checkDogState(dog);
owner2.checkDogState(dog);
owner1.checkDogState(dog);
owner2.checkDogState(dog);
dog.poop();
owner1.checkDogState(dog);
owner2.checkDogState(dog);
}
}
이 예제 코드에서는 강아지(Dog) 클래스의 상태 변화 메서드가 호출될 때마다 각 주인(Owner)이 직접 checkDogState 메서드를 호출하여 강아지의 상태를 확인할 수 있다. 그러나 이 방식은 주기적으로 상태를 조회하며 상태 변화를 감지하는 방법으로 비효율적이며 실시간으로 상태를 알리기 어렵다.
또한 다른 예시로는 다음과 같다.
public class Owner {
private String name;
private Dog dog; // Owner 클래스가 Dog 객체를 직접 참조
public Owner(String name, Dog dog) {
this.name = name;
this.dog = dog;
}
public void checkDogState() {
String action = dog.getAction();
System.out.println(name + "이(가) 강아지의 상태를 확인했습니다. 행동: " + action);
}
}
public class LegacyCodeExample {
public static void main(String[] args) {
Dog dog = new Dog();
Owner owner1 = new Owner("주인1", dog);
Owner owner2 = new Owner("주인2", dog);
// 상태 변화
dog.eat();
owner1.checkDogState();
dog.drink();
owner2.checkDogState();
dog.poop();
owner1.checkDogState();
}
}
이것은 옵저버 패턴의 장점을 설명하기 이전에 레거시에서의 안좋은 점을 부각하기 위해 추가한 예시이다.
Owner 클래스가 Dog 클래스를 직접적으로 참조하여 매우 강한 결합으로 되어있는 것을 확인 하면 된다.
Observer Pattern 구현 방법
observer pattern의 큰 틀은 다음과 같다.
인터페이스 Subject와 Observer를 설정하는 것이다.
Subject Interface
public interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers(String action);
}
subject의 인터페이스는 observer를 등록, observer 해지, 상태 변화를 observer들에게 알리는 메서드를 가지고 있는 것을 확인 할 수 있다.
Observer Interface
public interface Observer {
void update(String action);
}
observer 인터페이스는 관찰하고 있는 객체의 상태 변화(update)를 옵저버가 알 수 있는 메서드를 가지고 있다.
자 이제 이 인터페이스 두개가지고 똑같은 예시인 객체 Dog와 Owner를 구현해보자.
import java.util.ArrayList;
import java.util.List;
public class Dog implements Subject {
private List<Observer> observers = new ArrayList<>();
private String action;
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers(String action) {
for (Observer observer : observers) {
observer.update(action);
}
}
public void eat() {
action = "밥을 다 먹었다.";
notifyObservers(action);
}
public void drink() {
action = "물을 다 마셨다.";
notifyObservers(action);
}
public void poop() {
action = "똥을 쌌다.";
notifyObservers(action);
}
}
public class Owner implements Observer {
private String name;
public Owner(String name) {
this.name = name;
}
@Override
public void update(String action) {
System.out.println(name + "이(가) 강아지의 상태 변화를 감지했습니다. 행동: " + action);
}
}
public class ObserverPatternExample {
public static void main(String[] args) {
Dog dog = new Dog();
Owner owner1 = new Owner("주인1");
Owner owner2 = new Owner("주인2");
// 옵저버 등록
dog.registerObserver(owner1);
dog.registerObserver(owner2);
// 상태 변화
dog.eat();
dog.drink();
dog.poop();
}
}
옵저버 패턴을 적용한 이 예제 코드에서 확인 할 수 있다 시피,
이전 레거시 코드(문제가 되는 코드)와 달리 객체의 상태 변화가 있을 때 실시간으로 옵저버들에게 정보가 확인되는 구조이다.
즉, 알고 싶은 객체의 상태 변화를 별도의 함수 호출 없이 즉각적으로 알 수 있기 때문에 이벤트에 대한 처리를 자주해야 하는 프로그램이라면 매우 효율적인 프로그램을 작성할 수 있는 것이다.
Observer Pattern의 장단점
장점
1. Subject의 상태 변화를 주기적으로 조회하지 않아도 된다.
2. Subject와 Observer 객체 사이의 관계가 느슨하게 관리된다.
== Subject의 코드를 변경하지 않고도 새로운 Observer 클래스를 도입할 수 있어 개방 폐쇄 원칙(OCP) 준수한다
3. Runtime 시점에 Observer를 추가, 제거할 수 있다.
단점
1. Observer의 응답 순서를 보장하지 않는다.
2. Observer를 명시적으로 추가, 제거하기 때문에 메모리 누수가 발생할 가능성이 존재한다.
자바의 내장 옵저버 객체
자바에서 별도로 옵저버 패턴을 직접 구현하지 않아도 옵저버 패턴을 사용할 수 있도록 내장 옵저버 객체들이 존재한다.
1. Obserable과 Observer ( 자바 9버전 부터 deprecated가 되었다 )
2. PropertyChangeSuppoter와 PropertyChangeListener
java.util.Obserable

자바 9버전 부터는 deprecated가 되었다고 명시되어있고 여기서 확인할 점은 Observable은 class로 구현되어있어 후에 Dog와 같은 클래스를 구현하기 위해서는 extends를 사용하는것, Observer들을 Vector로 관리해 멀티 스레드 및 병렬처리에 안전하다는 점을 확인할 수 있다.
이 Observable으로 Dog를 구현해보면 다음과 같다.
import java.util.Observable;
public class Dog extends Observable {
private String action;
public void eat() {
action = "밥을 다 먹었다.";
this.setChanged();
this.notifyObservers(action);
}
public void drink() {
action = "물을 다 마셨다.";
this.setChanged();
this.notifyObservers(action);
}
public void poop() {
action = "똥을 쌌다.";
this.setChanged();
this.notifyObservers(action);
}
}
이 때 또 기존과 다른 점은 this.setChanged()로 변화를 알려줘야 notifyObservers()를 통해 이전과 같이 변화가 있을 때 알려주는것처럼 동작한다는 것이다.
java.util.Observer

마찬가지로 자바 9버전부터는 deprecated가 되었다.
import java.util.Observable;
import java.util.Observer;
public class Owner implements Observer {
private String name;
public Owner(String name) {
this.name = name;
}
@Override
public void update(Observable o, Object arg) {
if (o instanceof Dog) {
String action = (String) arg;
System.out.println(name + "이(가) 강아지의 상태 변화를 감지했습니다. 행동: " + action);
}
}
}
java.bean.PropertyChangeSuppoter

Observable처럼 클래스로 구현되어있는 것을 확인할 수있고 작게 thread-safe하다는 것도 확인할 수 있다.
또한 Observer 역할인 PropertyChangeLister들을 Map으로 관리하고 있는 모습이다.
그러나 이전에 상속이나 인터페이스 구현과 같은 방법이 아닌 이 PropertyChangeSupport를 필드로 두어 구현하는것이 다른 차이점 이다. 코드로 확인해보자.
public class Dog {
PropertyChangeSupport support = new PropertyChangeSupport(this);
private String action;
public void addObserver(PropertyChangeListener observer) {
if (observer != null) {
this.support.addPropertyChangeListener(observer);
}
}
public void removeObserver(PropertyChangeListener observer) {
if (observer != null) {
this.support.removePropertyChangeListener(observer);
}
}
public void notifyObservers(String newValue) {
support.firePropertyChange("event name", null, newValue);
}
public void eat() {
action = "밥을 다 먹었다.";
this.notifyObservers(action);
}
public void drink() {
action = "물을 다 마셨다.";
this.notifyObservers(action);
}
public void poop() {
action = "똥을 쌌다.";
this.notifyObservers(action);
}
}
java.bean.PropertyChangeListener

PropertyChangeListener는 인터페이스이고, 차이점은 PropertyChangeEvent인 객체로 달라진 상태(이벤트)를 확인 할 수 있다는 점이다.
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
public class Owner implements PropertyChangeListener {
private String name;
public Owner(String name) {
this.name = name;
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
System.out.println(name + "이(가) 강아지의 상태 변화를 감지했습니다. 행동: " + evt.getNewValue());
}
}
매번 디자인패턴 띡- 생성, 구조, 행동 그리고 무엇 무엇이 있고 정의에 대해서 겉으로만 읽을때와 달리
이렇게 하나의 내가 생각한 예제와 코드를 구현하니 옵저버 패턴에 대해서 조금 더 많이 학습하게 된 것 같다.
출처
'CS > 디자인패턴' 카테고리의 다른 글
[Design Pattern] Strategy Pattern(전략 패턴) (0) | 2024.06.02 |
---|---|
[Design Pattern] Factory Pattern(팩토리 패턴) (0) | 2024.06.01 |
[Design Pattern] Singleton Pattern(싱글톤 패턴) (0) | 2024.05.31 |
[Design Pattern] Builder Pattern(빌더 패턴) (1) | 2024.02.07 |
[Design Pattern] 디자인 패턴이란? (0) | 2024.01.23 |