인터페이스(Interface)
- 키보드나 디스플레이 따위처럼 사람과 컴퓨터를 연결하는 장치
- 기능에 대한 선언과 기능과 구현을 분리한다.
- 기능을 사용하는 통로
- 어떤 기능에 접근하는 접근점을 제공한다.
델리게이트(Delegate)
- 위임하다. 떠넘긴다는 뜻
- 두 객체간의 관계에서 어떤 객체가 기능을 수행할 때, 복잡한 기능을 개발하는 책임을 다른 객체로 떠넘긴다.
전략 패턴(스트레지티 패턴, Strategy Pattern)
- Def) 여러 알고리즘을 하나의 추상적인 접근점(인터페이스)을 만들어서 접근 점에서 서로 교환 가능하도록 하는 패턴을 말한다.
- 의도: 알고리즘들의 패밀리를 정의하고 각 패밀리를 별도의 클래스에 넣은 다음 그들의 객체들을 상호교환하도록 하는 행동 디자인 패턴을 말한다.
- 해결책: 특정 작업을 다양한 방식으러 수행하는 클래스를 선택한 후, 모든 알고리즘을 Strategies라는 별도의 클래스들로 추출한다.
- 전략 패턴 적용 방법
- 객체 내에서 한 알고리즘의 다양한 변형을 사용하고 싶을 때, 런타임 중에 한 알고리즘에서 다른 알고리즘으로 전환하고 싶을 때 사용한다.
- LSP(리스코프 치환법칙) - 일부 행동을 실행하는 방식에서만 차이가 있고 다른 부분은 유사한 클래스에 대해 적용한다.
- 클래스의 비즈니스 로직을 해당 로직의 콘텍스트에서 그리 중요하지 않을 수 있는 알고리즘들의 구현 세부 사항들로부터 고립시킨다. -
DIP(의존 관계 역전원칙) - 같은 알고리즘의 다른 변형들 사이를 전환하는 거대한 조건문이 클래스에 있는 경우에 사용한다.
- 객체 내에서 한 알고리즘의 다양한 변형을 사용하고 싶을 때, 런타임 중에 한 알고리즘에서 다른 알고리즘으로 전환하고 싶을 때 사용한다.
전략 패턴 구조
- 클라이언트(client): 전략 소유자 (사용자)는 특정 전략 객체를 만들어서 콘텍스트에 전달한다.
- 컨텍스트(Context): 구상 전략 중 하나에 대한 참조를 유지하고 전략 인터페이스를 통해서만 이 객체와 통신한다.
- 전략(Strategy) 인터페이스는 작업을 자체적으로 실행하는 게 아니라 Strategy 객체에 위임한다. 구상 전략을 실행하는데 필요한 공통 메서드를 포함한다.
- 구상 전략들(Strategies): 컨텍스트가 사용하는 알고리즘의 다양한 변형들을 구현한다.
- 서로 다른 전략끼리 의존하지 않도록 한다.
- 따라서 새로운 알고리즘을 추가하거나 기존 알고리즘을 수정할 수 있다.
전략 패턴 장점
- 런타임에 한 객체 내부에서 사용되는 알고리즘을 교환 가능
- 알고리즘의 구현 세부 정보들을 고립시킬 수 있다.
- 상속을 합성으로 대체 가능
- 개방 폐쇄 원칙 : 컨텍스트를 변경하지 않고도 새로운 전략 도입 가능
전략 패턴 단점
- 알고리즘이 몇 개 없고 변하지 않는다면 새로운 클래스들과 인터페이스들로 프로그램을 지나치게 복잡하게 만들 필요 없다.
- 클라이언트들은 적절한 전략을 선택할 수 있도록 전략 간 차이점을 알아야 한다.
전략 패턴 구현 방법
- 콘텍스트 클래스에서 자주 변경되는 알고리즘을 식별한다.
- 알고리즘의 모든 변형에 공통인 전략 인터페이스를 선언한다.
- 모든 알고리즘을 각각 하나씩 클래스들로 추출한다. 이들은 모두 전략 인터페이스를 implement한다.
- 콘텍스트 클래스에서 전략 객체에 대한 참조를 저장하기 위한 필드를 추가한 다음 해당 필드의 값을 대체하기 위한 세터를 제공한다.
- 클라이언트들은 콘텍스트를 적젏한 전략과 연관시켜야한다.
다른 패턴과의 관계
커맨드 패턴과 전략 패턴
- 공통점: 어떤 작업으로 객체를 매개변수화하는데 사용할 수 있다.
- 차이점
- 전략 패턴: 일반적으로 같은 작업을 수행하는 다양한 방법을 설명하므로 단일 콘텍스트 클래스 내에서 이러한 알고리즘들을 교환 가능하다.
- 커맨드 패턴: 모든 작업을 객체로 변환 가능하다. 작업의 매개변수들은 해당 객체의 필드들이 된다.
템플릿 메서드와 전략 패턴
- 템플릿 메서드: 상속을 기반으로 한다. 이 메서드는 자식 클래스들에서 알고리즘의 부분들을 확장해서 변경할 수 있도록 한다. 클래스 수준에서 정의하므로 static
- 전략 패턴: 합성을 기반으로 한다. 객체 수준에서 작동하므로 런타임에 행동들을 전환할 수 있도록 한다.
Ex) 신작 게임에서 캐릭터, 무기(칼, 검) 구현하기
- 무기를 접근점으로 만든다.
- 다음과 같이 두 개의 클래스를 만든다.
<hide/>
public interface Weapon {
public void attack();
}
<hide/>
public class Knife implements Weapon {
@Override
public void attack() {
System.out.println("칼 공격");
}
}
<hide/>
public class Sword implements Weapon {
@Override
public void attack() {
System.out.println("검 공격");
}
}
- 캐릭터
- setWeapon()을 통해 교환 가능하도록 한다.
- 구조 중에서 클라이언트에 해당한다. ???
<hide/>
public class GameCharacter {
private Weapon weapon;
// 교환 가능
public void setWeapon(Weapon weapon){
this.weapon = weapon;
}
// delegate
public void attack(){
if(weapon == null){
System.out.println("맨손 공격");
return;
}
weapon.attack();
}
}
- Main
<hide/>
public static void main(String[] args) {
GameCharacter character = new GameCharacter();
character.attack();
character.setWeapon(new Knife());
character.attack();
character.setWeapon(new Sword());
character.attack();
}
Note) 실행 결과
Ex) 유지 보수 요청 - 새로운 무기 도끼를 추가하라
<hide/>
public class Ax implements Weapon {
@Override
public void attack() {
System.out.println("도끼 공격");
}
}
Note) 실행 결과
- 무기를 추가할 때 효율적으로 추가 가능하다.
- 게임 캐릭터를 건드리지 않으면서 매인 클래스 변경도 없다.
궁금한 점 및 기타
- 전에 했던 편결이 프로젝트가 어댑터 패턴 vs 전략 패턴?
출처
https://www.inflearn.com/course/lecture?courseSlug=%EC%9E%90%EB%B0%94-%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4&unitId=3171 https://refactoring.guru/ko/design-patterns/strategy
https://refactoring.guru/ko/design-patterns/strategy
'디자인 패턴 (Design Pattern)' 카테고리의 다른 글
[구조 패턴] 퍼사드 패턴(Facade pattern) (0) | 2023.03.13 |
---|---|
[구조 패턴] 데코레이터 패턴(Decorator pattern, 장식자) (0) | 2023.03.12 |
[행동 패턴] 커맨드 패턴(Command Pattern, 명령 패턴) (0) | 2023.02.27 |
[행동 패턴] 템플릿 메서드(Template Method) (0) | 2023.02.27 |
[개요] 디자인패턴(Design Pattern)이란? (0) | 2023.01.28 |