2012-1
덕성여자대학교 정보미디어대학
교재: 자바언어로배우는디자인패턴입문(개정판)/YukiHiroshi저/김윤정역/영진닷컴
전략
– 적과 싸울 때의 책략
– 군대를 움직일 때의 작전
– 문제를 해결해 나갈 때의 방법 – 프로그래밍에서는 ‘알고리즘’
Strategy 패턴
– 알고리즘을 구현한 부분이 모두 교환 가능하도록 함
– 알고리즘(전략, 작전, 책략)을 교체해서 동일한 문제를 다른 방 법으로 해결하는 패턴
컴퓨터로 ‘가위바위보’ 하는 게임
두 가지 전략
– WinningStrategy
전략: 이기면 다음 번에도 같은 손을 내민다.
– ProbStrategy
전략: 바로 전에 내밀었던 손으로부터, 다음에 내밀 손을 확률적 으로 계산한다.
클래스와 인터페이스
클래스 다이어그램
위임
교체가 쉽다
Hand 클래스
– 가위바위보의 손을 나타내는 클래스
– (정적) hand 필드: 가위 손, 주먹 손, 보 손 세 개의 손을 가지고 있는 배열
– handvalue 필드: 주먹은 0, 가위는 1, 보는 2로 표현 – getHand( )
가위바위보를 나타내는 숫자로부터 해당 손을 반환함
– isStrongerThan( )
현재 손이 입력 인자로 들어온 손을 이기면 true를 반환함
– isWeakerThan( )
현재 손이 입력 인자로 들어온 손에게 지면 true를 반환함
Hand 클래스 – fight( )
현재 손이 입력인자 손과 무승부면 0, 이기면 1, 지면 -1을 반환함
우열 판정하는 수식
– 현재 손이 주먹(0)이고 입력 손이 가위(1)라면 – 또는, 현재 손이 가위(1)이고 입력 손이 보(2)라면 – 또는, 현재 손이 보(2)이고, 입력 손이 주먹(0)이라면 – 현재 손이 이긴다. => 1을 반환한다.
– 코드에서 this를 생략해도 된다.
– toString( ): 현재 손해 해당하는 문자열을 반환한다.
(this.handvalue + 1) % 3 == h.handvalue
(handvalue + 1) % 3 == h.handvalue
Strategy 인터페이스
– 가위바위보의 ‘전략’을 위한 추상 메소드를 모아놓은 곳 – nextHand( )
다음에 내밀 손을 얻기 위해 호출하는 메소드
이 메소드가 호출되면, Strategy 인터페이스를 구현한 클래스가 지혜를 모아 ‘다음 손’을 결정함
– study( )
다음 승부에 사용될 전략을 준비시키는 메소드
이긴 경우에는 Player가 study(true)를 호출하고,
진 경우에는 Player가 study(false)를 호출한다.
WinningStrategy 클래스
– Strategy 인터페이스를 구현한 클래스 – nextHand( )에서의 전략
직전의 승부에서 승리했으면, 동일한 손을 내민다
직전 승부에서 패했으면, 난수를 사용해서 다음 손을 정한다.
– java.util.Random 클래스 이용
• nextInt(3) : 0 부터 2 사이의 난수 정수 생성
어리석은 전략이다
– won 필드: 지난번 승부에서 이겼으면 true, 졌으면 false 저장 – prevHand 필드: 지난번 승부에서 내민 손 저장
ProbStrategy 클래스
– 좀 더 머리를 쓰는 전략
– history 필드: 과거의 승패를 유지하는 테이블
history[n번째 내민 손][n+1번째 내미는 손]
예
– history[0][0]: 주먹, 주먹 순으로 손을 내밀어서 이긴 횟수 – history[0][1]: 주먹, 가위 순으로 손을 내밀어서 이긴 횟수 – history[0][2]: 주먹, 보 순으로 손을 내밀어서 이긴 횟수
3 5 7
2 1 8
[0] [1] [2]
[0]
[1]
지금까지주먹 가위
ProbStrategy 클래스
– prevHandValue 필드: 지난번에 냈던 손 – currentHandValue 필드: 이번에 냈던 손 – nextHand( ): 다음에 낼 손을 반환함
handValue: 다음에 낼 손의 값을 저장함
전략
– 다음 페이지에…
ProbStrategy 클래스
– 전략(nextHand( ) 메소드를 참조할 것)
이번에 주먹을 냈더라면, history[0][0], history[0][1], history[0][2]로부터 다음 번에 낼 손의 확률을 계산하려고 한다.
history[0][0]=3, history[0][1]=5, history[0][2]=7 이 있었다면,
– 세 숫자를 다 더해서(3+5+7=15) 그 값을 이용해서 난수를 얻음 – 난수가 0이상 3미만이라면, 주먹을 내고
– 난수가 3이상 8미만이라면, 가위를 내고 – 난수가 8이상 15미만이라면, 보를 낸다.
주먹을 낸 다음에 냈던 손 중에서, 많이 이겼던 손을 다음에 낼 확률이
높다. [0] [1] [2]
ProbStrategy 클래스
– study( ) : 전략을 위한 준비 작업을 하는 메소드
이번에 이겼으면,
– history[직전에 냈던 손][이번에 냈던 손] 에 1을 더한다.
이번에 졌으면,
– history[직전에 냈던 손][이번에 안 냈던 손] 각각에 1을 더한다.
Player 클래스
– 가위바위보를 하는 사람을 표현한 클래스 – 생성 시, ‘이름’과 ‘전략’이 주어진다.
– 생성 시의 ‘전략’에 따라 다음에 내밀 손이 결정된다.
nextHand( ) 메소드 안에서 Strategy의 nextHand( )를 호출한다.
Strategy에게 위임한다.
– 이기든(win) 지든(lose) 무승부이든(even), 다음 승부를 위해서 Strategy의 study( ) 메소드를 호출한다.
win( ), lose( ), even( )
– 승패 횟수를 저장
wincount, losecount, gamecount 필드
Main 클래스
– 실제로 Player 둘을 생성해서 가위바위보 게임을 시킴 – 아래 두 문장을 똑같다.
“Winner: “ + player1
“Winner: “ + player1.toString( )
Strategy(전략)의 역할
– Strategy 패턴을 이용하기 위한 인터페이스(API) 결정 – 예제에서는 Strategy 인터페이스가 해당됨
ConcreteStrategy(구체적 전략)의 역할 – Strategy 인터페이스를 실제로 구현
– 구체적 전략(작전, 책략, 알고리즘)을 나타냄
– 예제에서는, WinningStrategy와 ProbStrategy가 해당됨
Context(문맥)의 역할
– Strategy를 이용하는 역할
– ConcreteStrategy 인스턴스를 가지고, 필요에 따라서 이를 이
클래스 다이어그램
위임 => Strategy를 쉽게 교체할 수 있다
일부러 Strategy 역할을 만들 필요가 있을까요?
– Strategy 역할을 구현하기만 한다면, ConcreteStrategy의 종류 를 변경하기가 쉽다.
예1: 예전의 알고리즘과 개량한 알고리즘의 속도를 비교하고 싶 은 경우, 간단히 교체해서 테스트할 수 있다.
예2: 장기 게임에서 사용자의 선택에 따라 사고 루틴의 레벨을 교 체하는 것도 간단하게 실행할 수 있다.
실행 중에 교체하는 것도 가능하다
– 프로그램 동작 중에 ConcreteStrategy 역할을 교체할 수 있다.
– 예: 메모리가 적은 환경에서는 SlowButLessMemoryStrategy를 사용하고, 메모리가 충분한 환경에서는
FastButMoreMemoryStrategy를 사용한다.
Flyweight 패턴 (20장)
Abstract factory 패턴 (8장)
State 패턴 (19장)
알고리즘(전략)을 쉽게 교체할 수 있는Strategy 패턴 – 위임(delegation) 덕택에 가능함
Player 클래스의 nextHand( ) 참조
10-4(계속)
– Sorter 인터페이스가 전략 역할을 담당함
<<interface>>
Sorter
SortAndPrint
10-4
– Insertion 소트 알고리즘
첫번째 반복 시
– 맨 왼쪽 자리에 들어갈 숫자부터 결정함
– 첫 번째 자리에 있는 숫자와 나머지를 차례대로 비교해서 필요 시 바꿈
5 3 4 2 3 5 4 2 3 5 4 2 2 5 4 3
2 5 4 3 2 4 5 3 2 3 5 4
2 3 5 4 2 3 4 5
i=0, j=1..3 i=1, j=2..3 i=2, j=3..3
10-4(계속)
– Bubble 소트 알고리즘
첫 번째 반복 시
– 맨 오른쪽에 놓일 숫자부터 결정함
– 인접한 숫자를 차례대로 서로 비교해서 필요하면 위치를 바꾼다.
5 3 4 2 3 5 4 2 3 4 5 2
3 4 2 5 3 4 2 5 3 2 4 5
3 2 4 5
2 3 4 5
10-4(계속)
– Comparable 인터페이스
크기 비교가 가능한 클래스들이 구현하는 인터페이스
– 예를 들어, String 들은 서로 크기 비교가 가능하므로 Comparable 인터페이스를 구현함
크기 비교 시 compareTo(Comparable c) 메소드 이용함
– 현재 객체와 인자로 들어온 객체 c의 크기를 비교함 – 반환값이 0 보다 크면, 현재 객체가 더 크다
– 반환값이 0 보다 작으면, 객체 c가 더 크다 – 반환값이 0 이면 두 객체의 크기가 같다.