전략 패턴(Strategy Pattern)으로 동작 방식을 유연하게 변경하기
소프트웨어 설계에서 전략 패턴(Strategy Pattern)은 매우 중요한 역할을 합니다. 프로그램의 동작 방식이 여러 가지가 있을 때, 이를 유연하게 관리하고 변경할 수 있게 해주는 디자인 패턴입니다. 이번 포스팅에서는 전략 패턴의 개념과 사용 목적을 설명하고, 실제 예제를 통해 어떻게 전략 패턴을 적용할 수 있는지 살펴보겠습니다.
1. 전략 패턴이란?
전략 패턴은 동작 방식을 캡슐화하여, 동적으로 전략을 변경할 수 있도록 하는 디자인 패턴입니다. 이 패턴은 어떤 기능을 수행할 여러 방법이 있을 때, 그 방법들을 전략(Strategy) 클래스에 정의하고, 클라이언트 코드에서는 실행 시점에 적절한 전략을 선택하여 사용할 수 있게 해줍니다.
즉, 행동을 객체로 캡슐화하여, 코드에서 필요에 따라 다른 행동을 선택하고 변경할 수 있게 해줍니다.
2. 전략 패턴의 사용 목적
전략 패턴은 다음과 같은 상황에서 유용합니다:
- 동작 방식을 동적으로 변경해야 할 때: 특정 조건에 따라 동작 방식이 달라져야 할 때, 그 로직을 캡슐화하여 변경이 용이하게 만들 수 있습니다.
- 여러 알고리즘을 선택적으로 사용해야 할 때: 동일한 문제를 해결하는 여러 알고리즘을 선택적으로 사용할 수 있게 해줍니다.
- 코드를 깔끔하고 유연하게 유지하고 싶을 때: 전략을 외부 클래스로 분리하여 클라이언트 클래스가 복잡해지는 것을 방지할 수 있습니다.
3. 전략 패턴 적용 예제
전략 패턴을 더 잘 이해하기 위해, 문자열을 다양한 방식으로 인코딩하는 예제를 통해 설명해보겠습니다.
구성 요소
- Strategy 인터페이스: 전략 패턴에서 공통된 인터페이스를 정의합니다.
- ConcreteStrategy 클래스들: 다양한 구체적인 전략들을 구현한 클래스들입니다.
- Context(클라이언트 클래스): 전략을 설정하고 해당 전략을 사용하는 클래스입니다.
예제 코드
// 1. 인코딩 전략 인터페이스
interface EncodingStrategy {
String encode(String text);
}
// 2. Base64 인코딩 전략
class Base64Strategy implements EncodingStrategy {
@Override
public String encode(String text) {
return Base64.getEncoder().encodeToString(text.getBytes());
}
}
// 3. 일반 텍스트 전략
class NormalStrategy implements EncodingStrategy {
@Override
public String encode(String text) {
return text;
}
}
// 4. 문자열에 "ABC"를 붙여서 보내는 전략
class AppendStrategy implements EncodingStrategy {
@Override
public String encode(String text) {
return "ABC" + text;
}
}
// 5. URL 인코딩 전략
class UrlEncodingStrategy implements EncodingStrategy {
@Override
public String encode(String text) {
try {
return URLEncoder.encode(text, StandardCharsets.UTF_8.toString());
} catch (Exception e) {
throw new RuntimeException("인코딩 실패", e);
}
}
}
// 6. 클라이언트 클래스 (Context)
class Encoder {
private EncodingStrategy encodingStrategy; // 전략을 저장하는 변수
// 전략을 설정하는 메서드
public void setEncodingStrategy(EncodingStrategy encodingStrategy) {
this.encodingStrategy = encodingStrategy;
}
// 설정된 전략에 따라 인코딩을 수행하는 메서드
public String getMessage(String message) {
return this.encodingStrategy.encode(message);
}
}
사용 예시
public class StrategyTest {
public static void main(String[] args) {
// 다양한 인코딩 전략 객체 생성
EncodingStrategy base64 = new Base64Strategy();
EncodingStrategy normal = new NormalStrategy();
EncodingStrategy append = new AppendStrategy();
EncodingStrategy urlEncoding = new UrlEncodingStrategy();
String message = "Hello World!";
Encoder encoder = new Encoder();
// 전략을 설정하고 메시지 인코딩 수행
encoder.setEncodingStrategy(base64);
System.out.println("Base64 Encoding: " + encoder.getMessage(message));
encoder.setEncodingStrategy(normal);
System.out.println("Normal Encoding: " + encoder.getMessage(message));
encoder.setEncodingStrategy(append);
System.out.println("Append Encoding: " + encoder.getMessage(message));
encoder.setEncodingStrategy(urlEncoding);
System.out.println("URL Encoding: " + encoder.getMessage(message));
}
}
출력 예시
Base64 Encoding: SGVsbG8gV29ybGQh
Normal Encoding: Hello World!
Append Encoding: ABCHello World!
URL Encoding: Hello+World%21
4. 전략 패턴의 장점
- 동적으로 전략을 변경 가능: 클라이언트 코드에서 전략을 쉽게 변경할 수 있어 유연한 코드 설계가 가능합니다.
- 확장성: 새로운 전략을 추가할 때 기존 코드에 영향을 주지 않으므로, 기존 코드를 수정하지 않고 새로운 전략을 추가할 수 있습니다.
- 결합도 감소: 전략 패턴을 사용하면 클라이언트 코드와 구체적인 알고리즘이 분리되므로 결합도가 낮아져 유지보수성이 향상됩니다.
5. 전략 패턴이 필요한 상황
- 동일한 행동을 여러 방법으로 처리할 수 있을 때: 예를 들어, 문자열을 인코딩하는 방식이 여러 가지일 수 있습니다. 이때 전략 패턴을 사용하면, 각 인코딩 방식을 독립적인 전략 클래스로 캡슐화하여 관리할 수 있습니다.
- 조건에 따라 행동이 달라져야 할 때: 예를 들어, 사용자가 선택한 옵션에 따라 계산 방식이 달라지는 경우, 전략 패턴을 활용하여 각 계산 방식을 전략으로 정의하고, 동적으로 전략을 변경하여 처리할 수 있습니다.
6. 결론
전략 패턴은 동작 방식을 변경하고자 할 때 매우 유용한 디자인 패턴입니다. 다양한 방법을 캡슐화하고 필요에 따라 선택적으로 적용할 수 있게 해줍니다. 이를 통해 코드의 유연성과 확장성을 높이고, 다양한 기능을 독립적으로 관리할 수 있습니다. 전략 패턴을 잘 활용하면 소프트웨어 설계를 깔끔하고 효율적으로 만들 수 있습니다.
실제 프로젝트에서 전략 패턴을 적용해보면, 여러 동작 방식이 존재하는 상황에서 어떻게 유용하게 사용할 수 있는지 알게 될 것입니다.
'JAVA' 카테고리의 다른 글
[JAVA] JVM이란? (0) | 2025.03.24 |
---|---|
[JAVA] 코딩테스트 필수 문법 정리 (0) | 2025.02.02 |
[JAVA] 어댑터 패턴(Adapter Pattern) (1) | 2025.01.09 |
[JAVA] 싱글톤 패턴(Singleton Pattern) (0) | 2025.01.09 |
[JAVA] 콜백 메서드란? (0) | 2025.01.09 |