전략
을 쉽게 바꿀 수 있도록 해줌
같은 문제를 해결하는 여러 알고리즘이 클래스별로 캡슐화되어 있고 이들이 필요할 때 교체할 수 있도록 함으로써 동일한 문제를 다른 알고리즘으로 해결할 수 있게 하는 디자인 패턴
전략
어떤 목적을 달성하기 위해 일을 수행하는 방식, 비즈니스 규칙, 문제를 해결하는 알고리즘
ex) 게임 프로그래밍에서 게임 캐릭터가 자신이 처한 상황에 따라 공격이나 행동하는 방식을 바꾸고 싶을 때
Strategy
: 인터페이스나 추상 클래스로 외부에서 동일한 방식으로 알고리즘을 호출하는 방법을 명시
ConcreateStrategy1, 2, 3
: 스트래티지 패턴에서 명시한 알고리즘을 실제로 구현한 클래스
Context
: 스트래티지 패턴을 이용하는 역할 수행. 필요에 따라 동적으로 구체적인 전략을 바꿀 수 있도록 setter 메서드 제공
public abstract class Robot{
private String name;
public Robot(String name){
this.name = name;
}
public String getName(){
return name;
}
public abstract void attack();
public abstract void move();
}
public class TaekwonV extends Robot{
public TaekwonV(String name){
super(name);
}
public void attack(){
System.out.println("I have Missile and can attack with it.");
}
public void move(){
System.out.println("I can only walk.");
}
}
public class Atom extends Robot{
public Atom(String name){
super(name);
}
public void attack(){
System.out.println("I have strong punch and can attack with it.");
}
public void move(){
System.out.println("I can fly.");
}
}
public class Client{
public static void main(String[] args){
Robot taekwonV = new TaekwonV("TaekwonV");
Robot atom = new Atom("Atom");
System.out.println("My name is " + taekwonV.getName());
taekwonV.move();
taekwonV.attack();
System.out.println();
System.out.println("My name is " + atom.getName());
atom.move();
atom.attack();
}
}
기존 로봇의 공격 또는 이동 방법을 수정하려면 어떤 변경 작업을 해야 하는가?
새로운 로봇을 만들어 기존의 공격 또는 이동 방법을 추가하거나 수정하려면?
- 기존의 코드 내용 수정 발생(OCP 위배)
- Atom 클래스의 move 메서드, TaekwonV 클래스의 move 메서드 기능의 중복
새로운 로봇에 기존의 공격 또는 이동 방법을 추가하거나 변경하려고 하면 문제 발생
다른 클래스와의 특정 메서드 중복 사용
시스템 변경에 따른 기존 모든 코드 수정
무엇이 변화되었는가? 에 중점
변화된 것을 찾은 후 캡슐화
외부에서 구체적인 이동 방식, 공격 방식을 담은 클래스 은닉화
공격, 이동을 위한 인터페이스 생성, 실현할 클래스를 만듦
클라이언트: 연관 관계를 이용해 이동 기능과 공격 기능의 변화 포함(Robot 클래스)
MovingStrategy, AttackStrategy 인터페이스를 포함해야 함
클래스 | 클래스 설명 |
---|---|
Robot | Robot 클래스, 이동과 공격을 실행하는 메서드, 이를 상속받아 구체적인 로봇을 만듦 |
Atom, TaekwonV | Robot 클래스를 상속받아 실제 로봇을 구현 |
<<interface>> AttackStrategy | 각 로봇이 취할 수 있는 공격 방법에 대한 인터페이스 |
PunchStrategy, MissileStrategy | 각 공격 방법을 실제로 구현함 |
<<interface>> MovingStrategy | 각 로봇이 취할 수 있는 이동 방법에 대한 인터페이스 |
WalkingStrategy, FlyingStrategy | 각 이동 방법을 실제로 구현함 |
구체적인 이동 방식과 공격 방식이 MovingStrategy, AttackStrategy 인터페이스에 의해 캡슐화
새로운 공격 방식 개발 시
OCP(Open-Closed Principle) 만족하는 설계
외부에서 로봇 객체의 이동 방식과 공격 방식을 임의대로 변경해야하는 메서드 생성
public abstract class Robot{
private String name;
private MovingStrategy movingStrategy;
private AttackStrategy attackStrategy;
public Robot(String name){
this.name = name;
}
public String getName(){
return name;
}
public void move(){
movingStrategy.move();
}
public void attack(){
attackStrategy.attack();
}
public void setMovingStrategy(MovingStrategy movingStrategy){
this.movingStrategy = movingStrategy;
}
public void setAttackStrategy(AttackStrategy attackStrategy){
this.attackStrategy = attackStrategy;
}
}
public class Atom extends Robot{
public Atom(String name){
super(name);
}
}
public class TaekwonV extends Robot{
public TaekwonV(String name){
super(name);
}
}
interface MovingStrategy{
public void move();
}
public class FlyingStrategy implements MovingStrategy{
public void move(){
System.out.println("I can fly.");
}
}
public class WalkingStrategy implements MovingStrategy{
public void move(){
System.out.println("I can only walk.");
}
}
interface AttackStrategy{
public void attack();
}
public class MissileStrategy implements AttackStrategy{
public void attack(){
System.out.println("I have Missile and can attack with it.");
}
}
public class PunchStrategy implements AttackStrategy{
public void attack(){
System.out.println("I have strong punch and can attack with it.");
}
}
public class Client{
public static void main(String[] args){
Robot taekwonV = new TaekwonV("TaekwonV");
Robot atom = new Atom("Atom");
taekwonV.setMovingStrategy(new WalkingStrategy());
taekwonV.setAttackStrategy(new MissileStrategy());
atom.setMovingStrategy(new WalkingStrategy()); // 이동 전략을 날아간다는 전략으로 설정
atom.setAttackStrategy(new PunchStrategy()); // 공격 전략을 펀치를 구사하는 전략으로 설정
System.out.println("My name is " + taekwonV.getName());
taekwonV.move();
taekwonV.attack();
System.out.println();
System.out.println("My name is " + atom.getName());
atom.move();
atom.attack();
}
}
Reference
포스트 유익하게 잘봤습니다. ㅎㅎ 오타나 하나 있는데, 마지막 설계 사진에 AttackStrategy가 아닌 MovingStrategy로 표기되어있습니다.