행동을 클래스로 캡슐화해서 동적으로 행동을 바꿀 수 있게 하는 패턴
자주 사용되는 경우 : 로깅(Logging), 트랜잭션 관리(Transaction Management), 정보 캐싱(Information Caching), 메소드 접근 제한(Method Access Control), 서비스 기능 확장(Extending Service Methods), 사용자 정의 데코레이터를 사용한 알림 서비스(Custom Decorator for Notification Service
Scenario)
스트레티지(Strategy) 장점
스트레티지(Strategy) 단점
템플릿 메서드(Templage Method)
일정 작업을 처리하는 부분을 서브클래스로 캡슐화해서 전체 수행 구조는 바꾸지 않으면서 특정 단계만 변경해서 수행하는 패턴
전략 패턴이 템플릿 메소드보다 유연하고 좋음
전략 패턴 : 합성(composition)을 통해 해결책을 강구하며, 대부분 인터페이스를 사용
템플릿 메서드 패턴 : 상속(inheritance)을 통해 해결책을 제시하며, 주로 추상 클래스나 구체적인 클래스를 사용
전략 패턴 예제) 텍스트를 입력 받고 서치하는 인터페이스와 오브젝트 구성
1. public interface SearchStrategy { : 검색 기능을 하는 인터페이스 구성// SearchStrategy 인터페이스: 다양한 검색 전략을 위한 공통 인터페이스 정의 public interface SearchStrategy { // 텍스트에서 패턴을 검색하는 메서드 // 검색된 패턴의 시작 인덱스를 반환, 패턴이 없으면 -1 반환 int search(String text, String pattern); }
전략 패턴 예제) 알고리즘 서비스를 구성하는 클래스
2. public class RegexSearch implements SearchStrategy { : RegexSearch기능을 하는 함수 생성 및 @Overrideimport java.util.regex.Matcher; import java.util.regex.Pattern; // RegexSearch 클래스: 정규 표현식을 이용한 검색 전략 구현 public class RegexSearch implements SearchStrategy { @Override public int search(String text, String pattern) { // Pattern과 Matcher 클래스를 사용하여 정규 표현식 검색 수행 Pattern p = Pattern.compile(pattern); Matcher m = p.matcher(text); if (m.find()) { // 패턴이 발견되면 시작 인덱스 반환 return m.start(); } // 패턴이 발견되지 않으면 -1 반환 return -1; } }
- public class SimpleSearch implements SearchStrategy { : SimpleSearch기능을 하는 인터페이스 구성
// SimpleSearch 클래스: 단순 문자열 검색 전략 구현 public class SimpleSearch implements SearchStrategy { @Override public int search(String text, String pattern) { // Java의 indexOf 메서드를 사용하여 단순 검색 수행 return text.indexOf(pattern); } }
전략 패턴 예제) 인터페이스 타입을 선택하는 클래스 구성
4. public class TextEditor { : 어떤 Search기능을 할당할지 지정해주는 클래스 구성
5. public void setSearchStrategy(SearchStrategy searchStrategy) { : setter 역할로 searchStrategy 알고리즘 선택
6. public int performSearch(String text, String pattern) { : 서치를 실행// TextEditor 클래스: 검색 전략을 사용하는 텍스트 편집기 public class TextEditor { // 현재 검색 전략을 저장하는 필드 private SearchStrategy searchStrategy; // 검색 전략을 설정하는 메서드 public void setSearchStrategy(SearchStrategy searchStrategy) { this.searchStrategy = searchStrategy; } // 설정된 검색 전략을 사용하여 텍스트에서 패턴을 검색하는 메서드 public int performSearch(String text, String pattern) { if (searchStrategy == null) { // 검색 전략이 설정되지 않은 경우 예외 발생 throw new IllegalStateException("Search strategy not set"); } // 설정된 검색 전략을 사용하여 검색 수행 return searchStrategy.search(text, pattern); } }
전략 패턴 예제) 메인 클래스 구성
import StrategyPattern.RegexSearch; import StrategyPattern.SimpleSearch; import StrategyPattern.TextEditor; public class MainByStrategy { // 메인 메서드: 예제 실행 public static void main(String[] args) { TextEditor editor = new TextEditor(); // 예제 텍스트 String text = "Hello, this is a simple text editor."; // 단순 검색 전략 사용 editor.setSearchStrategy(new SimpleSearch()); int index = editor.performSearch(text, "simple"); System.out.println("Simple Search: 'simple' found at index " + index); // 정규 표현식 검색 전략 사용 editor.setSearchStrategy(new RegexSearch()); index = editor.performSearch(text, "\\bsimple\\b"); System.out.println("Regex Search: '\\bsimple\\b' found at index " + index); } }
전체적 구조 :
객체의 상태 변화를 관찰하는 관찰자(옵저버) 목록을 객체에 등록해 상태가 변할 때마다 메서드 등을 통해 객체가 직접 옵서버에게 통지하게 하는 디자인 패턴
자주 사용되는 경우 : 이벤트 기반 아키텍처 (Event-Driven Architecture), 실시간 데이터 업데이트 (Real-Time Data Update), 모니터링 시스템 (Monitoring System), 데이터베이스 변경 감지 (Database Change Notification), 사용자 인터페이스 (User Interface), 알림 시스템 (Notification System)
옵저버(Observer) 장점
옵저버(Observer) 단점
옵저버 예제) 유저의 날씨 조회 기록 관리
1. interface Observer { : 다른 클래스의 기록을 조회 가능하도록 하는 인터페이스.package Observer; interface Observer { void display(WeatherAPI api); }
2.public class KoreanUser implements Observer { : 유저들의 날씨 조희 기록 클래스.
3.public void display(WeatherAPI api) { : 유저들의 날씨 조희 기록 형식 출력.package Observer; public class KoreanUser implements Observer { String name; public KoreanUser(String name) { this.name = name; } public void display(WeatherAPI api) { System.out.printf("%s님이 현재 날씨 상태를 조회함 : %.2f°C %.2fg/m3 %.2fhPa\n", name, api.temp, api.humidity, api.pressure); } }
옵저버 예제) 유저의 날씨 조회 기록 관리
4. interface Subject { : 객체들 관리 인터페이스package Observer; interface Subject { void registerObserver(Observer o); // 구독 추가 void removeObserver(Observer o); // 구독 삭제 void notifyObservers(); // Subject 객체의 상태 변경시 이를 모든 옵저버에게 알림 }
5. public class WeatherAPI implements Subject{ : 서브젝트 인터페이스 상속, 그리고 날씨 생성 및 유저 관리 서비스를 포함하는 클래스
6. public void measurementsChanged() { : 날씨 생성 기능
7. @Override public void registerObserver(Observer o) { : 옵저버로 구독자 등록
8. public void notifyObservers() { : 구독자 액티비티 기록 알림package Observer; import java.util.ArrayList; import java.util.List; import java.util.Random; public class WeatherAPI implements Subject{ float temp; // 온도 float humidity; // 습도 float pressure; // 기압 // 구독자들을 담아 관리하는 리스트 List<Observer> subscribers = new ArrayList<>(); public void measurementsChanged() { // 현재의 온습도 데이터를 랜덤값으로 얻는 것으로 비유하였다. temp = new Random().nextFloat() * 100; humidity = new Random().nextFloat() * 100; pressure = new Random().nextFloat() * 100; notifyObservers(); // 온습도 값이 변화하면 바로 옵저버들에게 발행 } @Override public void registerObserver(Observer o) { subscribers.add(o); } @Override public void removeObserver(Observer o) { subscribers.remove(o); } // 이벤트 전파 @Override public void notifyObservers() { for(Observer o: subscribers) { o.display(this); // 자신의 객체를 매개변수로 줘서 현재 자신의 상태를 구독자에게 알림 } } }
전체적 구조 :
https://inpa.tistory.com/entry/GOF-💠-템플릿-메소드Template-Method-패턴-제대로-배워보자
https://dev-coco.tistory.com/177