Java

[Design Pattern] 전략 패턴(Strategy Pattern)

구루싸 2020. 6. 29. 23:20
반응형
SMALL

정말 오랜만에 글을 작성하네요-_-

오늘의 학습 주제는

디자인 패턴 중 Strategy 패턴입니다

Stratey는 전략으로

적을 이기기 위한 작전이나

군대를 움직일 때의 방책 등을 의미합니다

프로그래밍에서 전략은

아무래도 알고리즘(Algorithm)이 되겠네요

Strategy 패턴은

이 알고리즘을 구현한 부분을

모두 교환할 수 있는 패턴입니다

먼저 Strategy 패턴의 역할들을 정리하면

다음과 같습니다

역할 설명
Strategy(전략) Strategy는 전략을 이용하기 위한 인터페이스를 결정
Concrete Strategy(구체적인 전략) Strategy의 인터페이스를 실제로 구현
Context(문맥) Context는 Strategy를 이용하는 역할

역시 직접 구현을 해봐야 알 수 있겠죠?^^;

1. 클래스(Class) Hand.java

package strategyPattern;

public class Hand {
	public static final int HANDVALUE_GUU = 0;
	public static final int HANDVALUE_CHO = 1;
	public static final int HANDVALUE_PAA = 2;
	public static final Hand[] hand = {
		new Hand(HANDVALUE_GUU),
		new Hand(HANDVALUE_CHO),
		new Hand(HANDVALUE_PAA),
	};
	private static final String[] name = {
			"주먹", "가위", "보",
	};
	private int handvalue;
	private Hand(int handvalue) {
		this.handvalue = handvalue;
	}
	public static Hand getHand(int handvalue) {
		return hand[handvalue];
	}
	public boolean isStrongerThan(Hand h) {
		return fight(h) == 1;
	}
	public boolean isWeakerThan(Hand h) {
		return fight(h) == -1;
	}
	private int fight(Hand h) {
		if ( this == h ) {
			return 0;
		} else if ( (this.handvalue + 1) % 3 == h.handvalue ) {
			return 1;
		} else {
			return -1;
		}
	}
	public String toString() {
		return name[handvalue];
	}
}

2. 클래스(Class) Player.java

package strategyPattern;

public class Player {
	private String name;
	private Strategy strategy;
	private int wincount;
	private int losecount;
	private int gamecount;
	public Player(String name, Strategy strategy) {
		this.name = name;
		this.strategy = strategy;
	}
	public Hand nextHand() {
		return strategy.nextHand();
	}
	public void win() {
		strategy.study(true);
		wincount++;
		gamecount++;
	}
	public void lose() {
		strategy.study(false);
		losecount++;
		gamecount++;
	}
	public void even() {
		gamecount++;
	}
	public String toString() {
		return "[" + name + ":" + gamecount + " games, " + wincount + " win, " + losecount + " lose]";
	}
}

3. 인터페이스(Interface) Strategy.java

package strategyPattern;

public interface Strategy {
	public abstract Hand nextHand();
	public abstract void study(boolean win);
}

4. 클래스(Class) WinningStrategy.java

package strategyPattern;
import java.util.*;
public class WinningStrategy implements Strategy {
	private Random random;
	private boolean won = false;
	private Hand prevHand;
	public WinningStrategy(int seed) {
		random = new Random(seed);
	}
	public Hand nextHand() {
		if ( !won ) {
			prevHand = Hand.getHand(random.nextInt(3));
		}
		return prevHand;
	}
	public void study(boolean win) {
		won = win;
	}
}

5. 클래스(Class) ProbStrategy.java

package strategyPattern;
import java.util.*;
public class ProbStrategy implements Strategy {
	private Random random;
	private int prevHandValue = 0;
	private int currentHandValue = 0;
	private int[][] history = {
			{ 1, 1, 1, },
			{ 1, 1, 1, },
			{ 1, 1, 1, },
	};
	public ProbStrategy(int seed) {
		random = new Random(seed);
	}
	public Hand nextHand() {
		int bet = random.nextInt(getSum(currentHandValue));
		int handvalue = 0;
		if ( bet < history[currentHandValue][0] ) {
			handvalue = 0;
		} else if ( bet < history[currentHandValue][0] + history[currentHandValue][1] ) {
			handvalue = 1;
		} else {
			handvalue = 2;
		}
		prevHandValue = currentHandValue;
		currentHandValue = handvalue;
		return Hand.getHand(handvalue);
	}
	private int getSum(int hv) {
		int sum = 0;
		for ( int i = 0; i < 3; i++ ) {
			sum += history[hv][i];
		}
		return sum;
	}
	public void study(boolean win) {
		if ( win ) {
			history[prevHandValue][currentHandValue]++;
		} else {
			history[prevHandValue][(currentHandValue + 1) % 3]++;
			history[prevHandValue][(currentHandValue + 2) % 3]++;
		}
	}
}

6. 클래스(Class) Test.java

import strategyPattern.*;
public class Test {
	public static void main(String[] args) {
		/* strategy Pattern */
		int seed1 = 314;
		int seed2 = 15;
		Player player1 = new Player("One", new WinningStrategy(seed1));
		Player player2 = new Player("Two", new ProbStrategy(seed2));
		for ( int i = 0; i < 10000; i++ ) {
			Hand nextHand1 = player1.nextHand();
			Hand nextHand2 = player2.nextHand();
			if ( nextHand1.isStrongerThan(nextHand2) ) {
				System.out.println("Winner:" + player1);
				player1.win();
				player2.lose();
			} else if ( nextHand2.isStrongerThan(nextHand1) ) {
				System.out.println("Winner:" + player2);
				player1.lose();
				player2.win();
			} else {
				System.out.println("Even...");
				player1.even();
				player2.even();
			}
		}
		System.out.println("Total result:");
		System.out.println(player1.toString());
		System.out.println(player2.toString());
	}
}

위의 코드를 보시면

Strategy 패턴은 알고리즘의 부분을

다른 부분과 분리해서 알고리즘의

인터페이스 부분만을 규정하고

위임에 의해 알고리즘을 이용합니다

위임은 느슨한 연결이므로

알고리즘을 용이하게 교환할 수 있습니다

위임에 대해서는 지난 Adapter 패턴에서 확인!!

2020/06/09 - [Java] - [Design Pattern] 어댑터 패턴(Adapter Pattern)

 

[Design Pattern] 어댑터 패턴(Adapter Pattern)

오늘 하루도 끝나가네요-_- 시간은 왜 이리도 빠른지 도전해 보고 싶은 것은 많은데 나이만 먹는거 같네요ㅜㅜ 아무튼 오늘은 지난 시간에 이어서 디자인 패턴 중 어댑터 패턴에 대해 학습하겠��

yssa.tistory.com

이 패턴을 이용한다면

정렬(Sort) 알고리즘들을

비교 분석하는데도 이용 가능할 것 같네요

시간이 난다면 한번 해봐야겠어요-_-

아무튼 오늘의 학습을 마치겠습니다

그럼 이만-_-

 

반응형
LIST