전략 패턴(Strategy Pattern)
- 직접 행위를 수정하지 않고 전략을 바꿔주기만 함으로써 행위를 유연하게 확장하는 방법
- 알고리즘을 구현한 부분이 모두 교환 가능하도록 함
- 알고리즘(전략, 작전, 책략)을 교체해서 동일한 문제를 다른 방법으로 해결하는 패턴
예제 프로그램
컴퓨터에서 '가위 바위 보'를 실행하는 프로그램. 두가지 전략을 쓴다.
전략1) Winning strategy : 이기면 다음에도 같은 손을 내린다.
전략2) Prob Strategy : 직전에 냈던 손에서 다음 낼 손을 확률적으로 계산한다.
다이어그램)
Source Code)
Hand.class
더보기
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];
}
}
Player.class
더보기
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" + "]";
}
}
Strategy 인터페이스
더보기
public interface Strategy {
public abstract Hand nextHand();
public abstract void study(boolean win);
}
WinningStrategy.class
더보기
import java.util.Random;
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;
}
}
ProbStrategy.class
더보기
import java.util.Random;
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]++;
}
}
}
Main.class
더보기
public class Main {
public static void main(String[] args) {
if (args.length != 2) {
System.out.println("Usage: java Main randomseed1 randomseed2");
System.out.println("Example: java Main 314 15");
System.exit(0);
}
int seed1 = Integer.parseInt(args[0]);
int seed2 = Integer.parseInt(args[1]);
Player player1 = new Player("�θ�", new WinningStrategy(seed1));
Player player2 = new Player("�ϳ�", 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());
}
}
출력결과)
Usage: java Main randomseed1 randomseed2
Example: java Main 314 15
연습문제 10-4)
다음 프로그램은 소트(정렬)를 실행하기 위한 클래스와 인터페이스입니다. 이 프로그램의 실행결과는 아래와 같습니다. 여기에서는 알고리즘으로 선택 정렬(selection sort)을 이용하고 있습니다. 다른 알고리즘을 표현하는 클래스를 Sorter의 인터페이스에 맞추어서 작성하십시오.
실행결과)
Dumpty, Bowman, Carroll, Elfland, Alice. //정렬 전
Alice, Bowman, Carroll, Dumpty, Elfland. //정렬 후
다이어그램)
Source code)
Sorter 인터페이스
import java.lang.Comparable;
public interface Sorter {
public abstract void sort(Comparable[] data);
}
SelectionSorter 클래스
public class SelectionSorter implements Sorter {
public void sort(Comparable[] data) {
for (int i = 0; i < data.length - 1; i++) {
int min = i;
for (int j = i + 1; j < data.length; j++) {
if (data[min].compareTo(data[j]) > 0) {
min = j;
}
}
Comparable passingplace = data[min];
data[min] = data[i];
data[i] = passingplace;
}
}
}
SortAndPrint 클래스
public class SortAndPrint {
Comparable[] data;
Sorter sorter;
public SortAndPrint(Comparable[] data, Sorter sorter) {
this.data = data;
this.sorter = sorter;
}
public void execute() {
print();
sorter.sort(data);
print();
}
public void print() {
for (int i = 0; i < data.length; i++) {
System.out.print(data[i] + ", ");
}
System.out.println("");
}
}
Main클래스
public class Main {
public static void main(String[] args) {
String[] data = {
"Dumpty", "Bowman", "Carroll", "Elfland", "Alice",
};
SortAndPrint sap = new SortAndPrint(data, new SelectionSorter());
sap.execute();
}
}
답)
QuickSorter는 quick sort algorithm을 사용한 클래스입니다.
QuickSorter 클래스
public class QuickSorter implements Sorter {
Comparable[] data;
public void sort(Comparable[] data) {
this.data = data;
qsort(0, data.length - 1);
}
private void qsort(int pre, int post) {
int saved_pre = pre;
int saved_post = post;
Comparable mid = data[(pre + post) / 2];
do {
while (data[pre].compareTo(mid) < 0) {
pre++;
}
while (mid.compareTo(data[post]) < 0) {
post--;
}
if (pre <= post) {
Comparable tmp = data[pre];
data[pre] = data[post];
data[post] = tmp;
pre++;
post--;
}
} while (pre <= post);
if (saved_pre < post) {
qsort(saved_pre, post);
}
if (pre < saved_post) {
qsort(pre, saved_post);
}
}
}
Main 클래스
public class Main {
public static void main(String[] args) {
String[] data = {
"Dumpty", "Bowman", "Carroll", "Elfland", "Alice",
};
SortAndPrint sap = new SortAndPrint(data, new QuickSorter());
sap.execute();
}
}
'JAVA' 카테고리의 다른 글
[디자인패턴] Decorator 패턴 (0) | 2022.04.28 |
---|---|
[디자인패턴] Composite 패턴 (0) | 2022.04.12 |
[디자인패턴] Prototype - 복사해서 인스턴스 만들기 (0) | 2022.03.31 |
[디자인패턴] Singleton (0) | 2022.03.21 |
[디자인패턴] Factory Method (0) | 2022.03.21 |