전략 패턴
정의:
객체들이 할 수 있는 행위 각각에 대해 전략 클래스를 생성하고, 유사한 행위들을 캡슐화 하는 인터페이스를 정의하여,
객체의 행위를 동적으로 바꾸고 싶은 경우 직접 행위를 수정하지 않고 전략을 바꿔주기만 함으로써 행위를 유연하게 확장하는 방법을 말합니다.
이 책에선 오리로 예시를 든다.
public Class Duck{
public quck(){};
public fly(){};
}
이렇게 되면 Duck을 상속받는 class 들은 무조건 fly와 quck을 날아야하기 때문에, 장난감 오리는 날지도 못하고, 꽉 하지도 못하는 데 상속을 통해 그 기능을 가져야한다. 여기서 전략 패턴이 필요하다.
그래서 이러한 행동을 클래스로 정의하는 것이 전략 패턴이다.
interface Fly{
public fly();
}
interface quck{
public quack();
}
이렇게 행동을 추상화 시키고, 이를 구현하여 처리하면 됩니다.
class toyquck implements quck{
public quack(){
System.out.println("난 장난감 오리 꽉할줄 모름")
};
}
이런식으로 하게되면 행동을 클래스로 갈아끼울 수 있기때문에, 유지보수가 쉬워지고, 객체지향적으로 바뀔 수 있다.
옵저버 패턴
객체의 상태 변화를 관찰하는 관찰자들, 즉 옵저버들의 목록을 객체에 등록하여 상태 변화가 있을 때마다 메서드 등을 통해 객체가 직접 목록의 각 옵저버에게 통지하도록 하는 디자인 패턴이다.
1. 상태 변화가 여러 곳에 영향을 줄 때
- 예를 들어, 데이터가 변경될 때 그것을 표시하는 여러 UI 요소들이 자동으로 업데이트되어야 하는 경우에 사용해. 이렇게 하면, 데이터가 바뀔 때마다 일일이 UI를 갱신하지 않고, 데이터만 바꿔도 UI들이 알아서 반응하게 할 수 있어.
예시: 날씨 애플리케이션에서 날씨 데이터가 바뀌면 여러 디스플레이 화면(스마트폰, 웹, TV 등)에 자동으로 업데이트될 때.
2. 객체 간의 결합도를 낮추고 싶을 때
- 객체들이 서로 직접적으로 의존하지 않고, 느슨하게 결합(loose coupling) 되어 있어야 할 때 사용해. 옵저버 패턴을 사용하면 주제(Subject)와 관찰자(Observer)가 서로 독립적으로 존재할 수 있어서 유지보수가 쉬워.
예시: 게시판 시스템에서 새로운 게시물이 추가되면 이메일 알림, 앱 푸시 알림, SMS 알림 등 다양한 채널로 알림을 보내야 할 때. 채널들이 주제에 강하게 결합되어 있지 않으면 각각의 알림 방식을 쉽게 추가하거나 제거할 수 있어.
3. 한 객체의 상태 변화에 대한 알림이 필요한 객체가 여러 개일 때
- 한 객체의 상태가 변할 때, 그 변화를 여러 객체에게 알려야 할 때 이 패턴이 유용해. 주제는 관찰자를 등록하고, 상태가 바뀔 때마다 자동으로 알려주기 때문에 여러 객체에게 일일이 알릴 필요가 없어.
예시: 주식 시장 애플리케이션에서 특정 주식의 가격이 변경될 때 여러 투자자들에게 알림을 보내는 상황.
4. 실시간으로 상태 변화를 감지해야 할 때
- 상태 변화가 실시간으로 반영되어야 할 때, 옵저버 패턴을 사용해. 상태 변화가 있을 때마다 자동으로 알림을 보내기 때문에 실시간 업데이트가 가능해.
예시: 게임에서 플레이어의 점수나 상태가 변경될 때, 실시간으로 스코어보드나 다른 UI에 반영하는 경우.
5. 구독/발행 모델을 만들고 싶을 때
- 옵저버 패턴은 **구독/발행 모델(Pub/Sub)**에도 자주 사용돼. 객체들이 주제에 "구독"하고, 주제가 변경될 때 "발행"하는 형태로 상태 변화를 통지할 수 있어.
예시: 뉴스 사이트에서 특정 주제에 대해 구독하고, 새로운 뉴스가 올라오면 이메일이나 알림으로 받아보는 경우.
코드 예시
// 주제 인터페이스
interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers();
}
// 관찰자 인터페이스
interface Observer {
void update(float temperature, float humidity, float pressure);
}
// 주제 구현 클래스
class WeatherData implements Subject {
private List<Observer> observers;
private float temperature;
private float humidity;
private float pressure;
public WeatherData() {
observers = new ArrayList<>();
}
public void registerObserver(Observer observer) {
observers.add(observer);
}
public void removeObserver(Observer observer) {
observers.remove(observer);
}
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(temperature, humidity, pressure);
}
}
// 날씨 정보가 변경될 때 호출되는 메소드
public void measurementsChanged() {
notifyObservers();
}
// 날씨 정보 설정 메소드
public void setMeasurements(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
}
// 관찰자 구현 클래스
class CurrentConditionsDisplay implements Observer {
private float temperature;
private float humidity;
public void update(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
display();
}
public void display() {
System.out.println("Current conditions: " + temperature + "F degrees and " + humidity + "% humidity");
}
}
// 사용 예시
public class WeatherStation {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay();
weatherData.registerObserver(currentDisplay);
// 날씨 정보 갱신
weatherData.setMeasurements(80, 65, 30.4f);
weatherData.setMeasurements(82, 70, 29.2f);
}
}
Spring에서는 옵저버 패턴을 사용하기 위해 **이벤트(Event)와 리스너(Listener)**를 많이 활용해. Spring Framework는 자체적으로 이벤트 처리 메커니즘을 제공하므로, 옵저버 패턴을 쉽게 구현할 수 있다.
EventListener에 대해서는 따로 독립적으로 글 하나를 쓰겠다.
'전공 서적 > 해드퍼스트 디자인 패턴' 카테고리의 다른 글
태태개발일지 - 펙토리패턴 & 싱글톤 패턴 (1) | 2024.11.07 |
---|