프로그래밍/자바 디자인패턴

디자인 패턴 Strategy 패턴

가카리 2012. 8. 1. 22:09
반응형

Strategy 인터페이스

 

 

 

package kch;

public interface Strategy {

        public abstract Hand nextHand();

        public abstract void study(booleanwin);

}

WinningStrategy 클래스

package kch;

import java.util.Random;

public class WinningStrategy implementsStrategy{

        //이 클래스는 전판이 이기면 다음에도똑같은 것을 내는 전략을 취함

              

        privateRandom random;//랜덤변수 생성 목적

        private boolean won = false;//전판이 이겼는지 졌는지에 대한 필드

        private HandprevHand;//전판에 내밀었던 손을 저장함

        publicWinningStrategy(int seed){

       

               random = new Random(seed);

       

        }

        public HandnextHand(){

              

               if(!won){//만약에지면 랜덤으로 만듬 0,1,2의 값중에 하나가 나옴

              

                       prevHand =Hand.getHand(random.nextInt(3));//

       

               }

              

               returnprevHand;//이겼다면 똑같은 손을 내밀게 됨.

       

        }

       

        public void study(boolean win){

       

               won = win;//

        }

              

}

ProbStrategy 클래스

package kch;

import java.util.Random;

public class ProbStrategy implementsStrategy{

       

        privateRandom random;

        private int prevHandValue = 0;

        private int currentHandValue = 0;

        private int[][] history = {

                       {1,1,1,},

                       {1,1,1,},

                       {1,1,1,},

        };

        //[0][1] 이면 0이니까 이전에 주먹을 내고 이번에 가위를 냈을 때의 과거의 승수

        //[0][2] 이면 이전에 주먹을 내고 이번에보를 냈을때의 과거의 승수

       

        publicProbStrategy(int seed){

       

               random = new Random(seed);

       

        }

       

        public HandnextHand(){

       

               int bet= random.nextInt(getSum(currentHandValue));//랜덤변수 발생

               //이때 getSum을 쓰는데

               //history[0][0] 값이 3

               //history[0][1] 값이 5

               //history[0][2] 값이 7

               //이면 주먹:가위: = 3:5:7로계산에 의한 난수값을 얻는다

               // 3/15의 확률로 주먹이 나오고 5/15로 가위 7/15로 보자기가 나오게 된다.

              

               inthandvalue = 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;

              

               returnHand.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 ]++;

              

               }

        }

}

Hand 클래스

package kch;

public class Hand {

       

        public static final int HANDVALUE_MUK = 0;

        public static final int HANDVALUE_JJI = 1;

        public static final int HANDVALUE_BBA = 2;

        public static final Hand[] hand = {

               newHand(HANDVALUE_MUK),

               newHand(HANDVALUE_JJI),

               newHand(HANDVALUE_BBA)

        };

       

        private static final String[] name = {

               "주먹", "가위", ""

               };

        private int handvalue;

        privateHand(int handvalue){

              

               this.handvalue= handvalue;

              

        }

       

        public static Hand getHand(inthandvalue){

              

               returnhand[handvalue];

              

        }

       

        public boolean isStrongerThan(Hand h){//this h 를 이길경우 true

              

               returnfight(h) == 1;

              

        }

       

        public boolean isWeakerThan(Hand h){//this h에게 질 경우true

              

               returnfight(h) == -1;

              

        }

       

        private int fight(Hand h){

               if(this == h){//무승부면

                      

                       return 0;

                      

               }else if((this.handvalue + 1) % 3 == h.handvalue){//this

                      

                       return 1;

              

               }else{//this

              

                       return -1;

              

               }

        }

        publicString toString(){//문자열 표현으로 변환

               returnname[handvalue];

        }

}

Player 클래스

package kch;

public class Player {

        privateString name;

        privateStrategy strategy;

        private int wincount;

        private int losecount;

        private int gamecount;

       

        publicPlayer(String name, Strategy strategy){

              

               this.name = name;

              

               this.strategy = strategy;

        }

       

        public HandnextHand(){

              

               return strategy.nextHand();

              

        }

       

        public void win(){

              

               strategy.study(true);//넘기는 값은 현재 게임이 이겼는지 졌는지

               wincount++;

               gamecount++;

              

        }

       

        public void lose(){

              

               strategy.study(false);//넘기는 값은 현재 게임이 이겼는지 졌는지

               losecount++;

               gamecount++;

              

        }

       

        public void even(){

              

               gamecount++;

       

        }

       

        publicString toString(){

              

               return "[" + name + ":" +gamecount + "games," + wincount + "win, " + losecount +

                              " lose" + "]";

        }

}

Main 클래스

package kch;

public class Main {

        public static void main(String [] args){

              

               if(args.length != 2){

                       System.out.println("error.input the 2 parameter");

                       System.exit(0);

               }

              

               intseed1 = Integer.parseInt(args[0]);

               intseed2 = Integer.parseInt(args[1]);

              

               Player player1 = new Player("두리", new WinningStrategy(seed1));

               //두리는 WinningStrategy 전략을 씀.

               Player player2 = new Player("하나", new ProbStrategy(seed2));              

               //하나는 ProbStrategy 전략을 씀.

              

               for(int i = 0; i < 10000; i++){//만번 돌림

                      

                       Hand nextHand1 =player1.nextHand();//다음 손을 냄.

                       Hand nextHand2 =player2.nextHand();//다음 손을 냄.

                      

                       if(nextHand1.isStrongerThan(nextHand2)){//비교함

                              //player1 이길때

                              System.out.println("Winner:" + player1);

                              player1.win();

                              player2.lose();

                       }

                       else if(nextHand2.isStrongerThan(nextHand1)){

                              //player2 질때

                              System.out.println("Winner:" + player2);

                              player1.lose();

                              player2.win();

                       }

                       else{

                             

                              //비길때.

                              System.out.println("Even..");

                              player1.even();

                              player2.even();

                       }

       

               }

              

               System.out.println("Totalresult: ");

               System.out.println(player1.toString());//미리 정의한 글자가 나옴,

               System.out.println(player2.toString());

              

        }

}

 

 

 

이러한 전략 패턴은

메모리가 적은 환경에서는 메모리 필요가 적은 클래스를 사용하고 많을 때는 메모리가 많이 소비되는 클래스를 사용하는여러 전략을 둘 수 있게합니다.

즉 그때그때 맞춰나갈 수 있다는 것이 장점입니다.

 

 

반응형