오늘은 디자인 패턴 스터디 4번째 항목인 전략패턴에 대하여 알아보겠습니다.
전략 패턴(Strategy Pattern)
전략 패턴은 객체지향 소프트웨어 디자인에서 사용되는 디자인 패턴 중 하나입니다.
이 패턴은 알고리즘군을 정의하고 각각을 캡슐화하여 실행(런타임) 중에 알고리즘을 선택하여 객체의 동작을 변경할 수 있도록 해줍니다.
이는 프로그램의 유연성과 확장성을 높일 수 있습니다.
전략 패턴의 주요 요소
전략(Strategy)
전략은 알고리즘을 나타내며, 인터페이스를 통해 정의됩니다.
각각의 전략은 특정한 알고리즘을 실행하는 메서드를 포함합니다.
컨텍스트(Context)
컨텍스트는 전략을 사용하는 클라이언트 객체입니다.
컨텍스트는 전략 객체를 갖고있으며, 실행 중에 전략을 교체할 수 있습니다.
전략 패턴의 클라이언트(Client)
클라이언트는 컨텍스트를 사용하여 전략을 실행합니다. 클라이언트는 컨텍스트에 전략을 설정하고, 컨텍스트를 통해 해당 전략을 실행합니다.
전략 패턴 예시 코드
아래는 간단한 가격 계산기를 구현하고, 다양한 할인 전략을 적용해 가격을 계산하는 예제 코드입니다.
// 전략 인터페이스
interface DiscountStrategy {
double applyDiscount(double price);
}
이 인터페이스는 모든 할인 전략 클래스가 구현해야 하는 메서드를 정의합니다.
applyDiscount(double price) 메서드는 주어진 가격에 할인을 적용한 결과를 반환합니다.
// 고정 할인 전략
class FixedDiscountStrategy implements DiscountStrategy {
private double discount;
public FixedDiscountStrategy(double discount) {
this.discount = discount;
}
public double applyDiscount(double price) {
return price - discount;
}
}
// 백분율 할인 전략
class PercentageDiscountStrategy implements DiscountStrategy {
private double percentage;
public PercentageDiscountStrategy(double percentage) {
this.percentage = percentage;
}
public double applyDiscount(double price) {
return price * (1 - percentage / 100);
}
}
위의 두가지 클래스는 할인을 적용하는 전략을 구현합니다.
각각 고정된 금액의 할인 및 백분율 만큼의 할인을 적용하는 전략을 구현하고 있습니다.
생성자를 통해 할인 금액(비율)을 전달받고, appliDiscount(double price) 메서드에서 해당 할인을 적용합니다.
// 가격 계산기
class PriceCalculator {
private DiscountStrategy discountStrategy;
public PriceCalculator(DiscountStrategy discountStrategy) {
this.discountStrategy = discountStrategy;
}
public double calculatePrice(double price) {
return discountStrategy.applyDiscount(price);
}
}
위의 클래스는 할인 전략을 받아들여, 가격을 계산하는 기능을 제공합니다.
생성자를 통해 할인 전략 객체를 받아들이고, calculatePrice(double price) 메서드에서 해당 전략을 사용해 가격을 계산합니다.
// 클라이언트 코드
public class Main {
public static void main(String[] args) {
// 고정 할인 전략 사용
DiscountStrategy fixedDiscount = new FixedDiscountStrategy(5); // 5원 할인
PriceCalculator calculator = new PriceCalculator(fixedDiscount);
double discountedPrice1 = calculator.calculatePrice(100);
System.out.println("Discounted Price with Fixed Discount: " + discountedPrice1);
// 백분율 할인 전략 사용
DiscountStrategy percentageDiscount = new PercentageDiscountStrategy(10); // 10% 할인
calculator = new PriceCalculator(percentageDiscount);
double discountedPrice2 = calculator.calculatePrice(100);
System.out.println("Discounted Price with Percentage Discount: " + discountedPrice2);
}
}
Main클래스는 프로그램의 진입점이며, 두 가지 다른 종류의 할인 전략을 만들고,
각각의 전략을 PriceCalculator 객체에 전달하여 가격을 계산합니다.
계산된 가격은 콘솔에 출력됩니다.
위와 같은 예시 코드는 전략 패턴을 사용해 가격 계산을 유연하게 구현한 예시입니다.
전략 패턴을 사용하면 새로운 할인 전략을 추가하거나 기존의 전략을 변경하는 것이 쉬워지므로,
시스템의 확장성이 높아집니다.
전략 패턴의 장점
유연성(Flexibility)
전략 패턴을 사용하면 알고리즘을 독립적으로 캡슐화하여 교체할 수 있습니다.
이는 알고리즘을 변경하거나 확장 시 유용하며, 시스템의 유연성을 확장시킵니다.
확장성(Extensibility)
새로운 전략을 추가하거나 기존의 전략을 수정하여 시스템을 확장하기가 쉽습니다.
새로운 전략을 추가할 때 기존의 코드를 변경할 필요 없어 유지보수에 용이합니다.
가독성(Readability)
전략 패턴을 사용하면 각각의 전략을 별도의 클래스로 분리하여 코드를 간결하고 가독성 있게 유지할 수 있습니다.
각 전략의 목적과 동작이 명확하게 드러나므로 코드의 이해와 유지보수가 쉬워집니다.
테스트 용이성(Testability)
전략 패턴을 사용하면 각각의 전략을 독립적으로 테스트할 수 있습니다.
이는 모듈화된 코드를 테스트하기 쉽게 만들어주어 소프트웨어의 품질을 향상시킵니다.
전략 패턴의 단점
클래스 수 증가(Class Overhead)
전략 패턴을 사용하면 각각의 전략을 별도의 클래스로 구현해야 하므로 클래스 수가 증가할 수 있습니다.
복잡성(Complexity)
전략 패턴을 구현할 때 객체 간의 상호작용이 복잡해질 수 있습니다.
특히, 전략 객체가 컨텍스트 객체와 밀접하게 연결되어 있을 때 복잡성이 증가할 수 있습니다.
선택의 부담(Selection Overhead)
실행 중에 전략을 선택하는 로직을 추가해야하므로 선택 로직의 부담을 줄 수 있습니다.
이로인해 성능이 저하될 수 있습니다.
전역 데이터 공유(Global Data Sharing)
전략 객체 사이에서 데이터를 공유하려는 경우, 전략 패턴은 복잡해질 수 있습니다.
이 경우 데이터 공유를 위한 추가 메커니즘이 필요할 수 있습니다.
전략 패턴의 실사용
자바의 컬렉션 프레임워크
자바의 컬렉션 프레임워크에서는 정렬 알고리즘을 선택할 수 있도록
Comparator 인터페이스를 제공합니다.
이 인터페이스를 구현한 클래스들은 다양한 정렬 전략을 제공하며, 이를 사용하여 컬렉션을 정렬할 수 있습니다.
자바의 스트림 API
자바 8에서 추가된 스트림 API에서도 전략 패턴이 사용됩니다.
예를 들어, 스트림의 sorted() 메서드는 요소를 정렬하는데 전략을 사용합니다.
정렬 순서를 지정하는 Comparator 객체를 전달하여 다양한 정렬 전략을 사용할 수 있습니다.
자바스크립트의 이벤트 처리
웹 애플리케이션에서 이벤트 처리에 전략 패턴이 사용될 수 있습니다.
예를 들어, 클릭 이벤트를 처리하는데 각각 다른 전략을 적용할 수 있습니다.
이를 통해 동일한 이벤트에 대해 다양한 동작을 수행할 수 있습니다.
게임 개발
게임 엔진에서는 AI 행동을 구현하는데 전략 패턴을 사용할 수 있습니다.
각 캐릭터나 유닛의 AI 동작을 각각 다른 전략으로 구현하여 쉽게 교체할 수 있습니다.
요약
전략 패턴은 실행 중에 알고리즘을 선택할 수 있도록 하여 객체의 동작을 동적으로 변경할 수 있게 하는 행위 디자인 패턴입니다.
이 패턴은 알고리즘을 캡슐화하여 동일한 인터페이스를 사용하는 여러 알고리즘을 교체할 수 있도록 합니다.
주요 요소는 전략(Strategy), 컨텍스트(Context), 클라이언트(Client)가 있으며,
각 전략은 독립적으로 캡슐화되어 있습니다.
컨텍스트는 전략 객체를 사용하여 동작하고, 클라이언트는 컨텍스트를 통해 전략을 선택 및 사용합니다.
이를 통해 코드의 재사용성, 확장성 및 유지보수성을 높일 수 있습니다.
오늘은 전략 패턴에 대하여 공부해보았습니다.
메소드는 같지만, 안의 알고리즘이 다를 때, 사용하기 좋은 패턴 같다고 느꼈습니다.
디자인 패턴 스터디가 4번째인데,
비슷하면서도 각각의 매력이 다른게 참 재미있네요:>
다들 즐거운 개발공부 되세요 :)
'Design Pattern' 카테고리의 다른 글
Design Pattern | 브리지 패턴(Bridge Pattern) (0) | 2024.08.29 |
---|---|
Design Pattern | 빌더 패턴(Builder Pattern) (2) | 2024.04.26 |
Design Pattern | 데코레이터 패턴(Decorator Pattern) (1) | 2024.03.22 |
Design Pattern | 컴포지트 패턴(Composite Pattern) (0) | 2024.02.22 |
Design Pattern | 추상 팩토리 패턴(Abstract Factory Pattern) (0) | 2024.01.30 |