[GoF] Strategy 패턴 : 알고리즘을 모두 바꾼다 [같은 문제를 다른 방법으로 해결하기 쉽게 만들어주는 패턴]

2023. 8. 30. 12:12·◈ Study/디자인패턴(GoF)🥞
728x90

- Strategy 패턴 : 알고리즘을 모두 바꾼다

Strategy 패턴은 스위치 전환하듯 알고리즘을 바꿔, 같은 문제를 다른 방법으로 해결하기 쉽게 만드는 패턴이다.

Strategy 패턴 / 참고자료 : https://refactoring.guru/ko/design-patterns/strategy

- 어떤 경우에 사용할까?

보통 프로그래밍을 하다 보면 알고리즘을 메서드 안에 녹아드는 형태로 구현하기 쉬운데, Strategy 패턴을 사용하면 알고리즘 부분을 다른 부분과 의도적으로 분리한다. 이로 인해 알고리즘을 용이하게 전환할 수 있다.

- 예제 코드

Strategy 패턴 클래스 다이어그램 / 참고자료 : JAVA 언어로 배우는 디자인 패턴 입문


이름 설명
Hand 가위바위보의 '손'을 나타내는 클래스
Strategy 가위바위보의 '전략'을 나타내는 인터페이스
WinningStrategy 이기면 다음에도 같은 손을 내는 전략을 나타내는 클래스
ProbStrategy 직전 손에서 다음 손을 확률적으로 계산하는 전략을 나타내는 클래스
Player 가위바위보를 하는 플레이어를 나타내는 클래스
Main 동작 테스트용 클래스

- Hand형

public enum Hand {
	// 가위 바위 보를 나타내는 세 개의 enum 상수
	ROCK("바위", 0),
	SCISSORS("가위", 1),
	PAPER("보", 2);
	
	// enum이 가진 필드
	private String name;   // 가위 바위 보 손의 이름
	private int handvalue; // 가위 바위 보 손의 값
	
	private static Hand[] hands = {
			ROCK, SCISSORS, PAPER
	};

	// 생성자
	private Hand(String name, int handvalue) {
		this.name = name;
		this.handvalue = handvalue;
	}
	
	// 손의 값으로 enum 상수를 가져온다
	public static Hand getHand(int handvalue) {
		return hands[handvalue];
	}
	
	// this가 h보다 강할 때 true
	public boolean isStrongerThan(Hand h) {
		return fight(h) == 1;
	}
	
	// this가 h보다 약할 때 true
	public boolean isWeakerThan(Hand h) {
		return fight(h) == -1;
	}
	
	// 무승부는 0, this가 이기면 1, 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;
		}

	}

	// 가위 바위 보의 문자열 표현
	@Override
	public String toString() {
		return name;
	}
}

- Strategy 인터페이스

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

- WinningStrategy 클래스

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);
	}
	
	@Override
	public Hand nextHand() {
		if(!won) {
			prevHand = Hand.getHand(random.nextInt(3));
		}
		return prevHand;
	}
	@Override
	public void study(boolean win) {
		won = win;
	}
}

- ProbStrategy 클래스

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);
	}

	@Override
	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 handvalue) {
		int sum = 0;
		for(int i = 0 ; i < 3 ; i++) {
			sum += history[handvalue][i];
		}
		return sum;
	}

	@Override
	public void study(boolean win) {
		if(win) {
			history[prevHandValue][currentHandValue]++;
		} else {
			history[prevHandValue][(currentHandValue + 1) % 3]++;
			history[prevHandValue][(currentHandValue + 2) % 3]++;
		}
	}
}

- Player 클래스

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++;
	}

	@Override
	public String toString() {
		return "["
			+ name + ":"
			+ gamecount + " games, "
			+ wincount + " win, "
			+ losecount + " lose"
			+ "]";
	}
}

- Main 클래스

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("KIM", new WinningStrategy(seed1));
		Player player2 = new Player("LEE", 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);
		System.out.println(player2);
	}
}

 

참고문헌 : 유키 히로시 저/김성훈 역(2022), JAVA 언어로 배우는 디자인 패턴 입문, 영진닷컴

참고자료 : https://refactoring.guru/ko/design-patterns/strategy


728x90
'◈ Study/디자인패턴(GoF)🥞' 카테고리의 다른 글
  • [GoF] Decorator 패턴 : 장식들과 내용물을 동일시한다 [객체에 장식을 더해 가는 패턴]
  • [GoF] Composite 패턴 : 그릇과 내용물을 동일시한다 [재귀적인 구조를 만드는 패턴]
  • [GoF] Bridge 패턴 : 기능 계층과 구현 계층을 나눈다 [기능의 클래스 계층과 구현의 클래스 계층을 연결하는 패턴]
  • [GoF] Builder 패턴 : 복잡한 인스턴스를 조립한다 [구조를 가진 인스턴스를 만들어 가는 패턴]
예르미(yermi)
예르미(yermi)
끊임없이 제 자신을 계발하는 개발자입니다👨🏻‍💻
  • 예르미(yermi)
    예르미의 코딩노트
    예르미(yermi)
  • 전체
    오늘
    어제
    • 분류 전체보기 (937)
      • ◎ Java (133)
        • Java☕ (93)
        • JSP📋 (26)
        • Applet🧳 (6)
        • Interview👨🏻‍🏫 (8)
      • ◎ JavaScript (48)
        • JavaScript🦎 (25)
        • jQuery🌊 (8)
        • React🌐 (2)
        • Vue.js🔰 (6)
        • Node.js🫒 (3)
        • Google App Script🐑 (4)
      • ◎ HTML5+CSS3 (17)
        • HTML5📝 (8)
        • CSS3🎨 (9)
      • ──────────── (0)
      • ▣ Framework (67)
        • Spring🍃 (36)
        • Spring Boot🍀 (12)
        • Bootstrap💜 (3)
        • Selenium🌕 (6)
        • MyBatis🐣 (10)
      • ▣ Tools (47)
        • API🎯 (18)
        • Library🎲 (15)
        • JitPack🚀 (3)
        • Jenkins👨🏻 (7)
        • Thymeleaf🌿 (4)
      • ▣ Server (32)
        • Apache Tomcat🐱 (14)
        • Apache HTTP Server🛡️ (1)
        • Nginx🧶 (7)
        • OracleXE💿 (4)
        • VisualSVN📡 (4)
      • ▣ OS : 운영체제 (18)
        • cmd : 명령프롬프트💻 (10)
        • Linux🐧 (8)
      • ▣ SQL : Database (56)
        • Oracle SQL🏮 (26)
        • PL SQL💾 (9)
        • MySQL🐬 (6)
        • MariaDB🦦 (6)
        • H2 Database🔠 (3)
        • SQL 실전문제🐌 (6)
      • ────────── (0)
      • ◈ Human Project (86)
        • Mini : Library Service📚 (15)
        • 화면 설계 [HTML]🐯 (10)
        • 서버 프로그램 구현🦁 (15)
        • Team : 여수어때🛫 (19)
        • Custom : Student🏫 (9)
        • Custom : Board📖 (18)
      • ◈ Yermi Project (40)
        • 조사모아(Josa-moa)📬 (5)
        • Riddle-Game🧩 (6)
        • 맛있을 지도🍚 (2)
        • 어디 가! 박대리!🙋🏻‍♂️ (5)
        • 조크베어🐻‍❄️ (4)
        • Looks Like Thirty🦉 (2)
        • Toy Project💎 (12)
        • 오픈소스 파헤치기🪐 (4)
      • ◈ Refactoring (15)
        • Mini : Library Service📚 (8)
        • 서버 프로그램 구현🦁 (1)
        • Team : 여수어때🛫 (0)
        • 쿼리 튜닝일지🔧 (6)
      • ◈ Coding Test (89)
        • 백준(BOJ)👨🏻‍💻 (70)
        • 프로그래머스😎 (2)
        • 코드트리🌳 (7)
        • 알고리즘(Algorithm)🎡 (10)
      • ◈ Study (102)
        • 기초튼튼 개발지식🥔 (25)
        • HTTP 웹 지식💡 (4)
        • 클린코드(Clean Code)🩺 (1)
        • 디자인패턴(GoF)🥞 (12)
        • 다이어그램(Diagram)📈 (4)
        • 파이썬(Python)🐍 (16)
        • 에러노트(Error Note)🧱 (34)
        • 웹 보안(Web Security)🔐 (6)
      • ◈ 공부모임 (39)
        • 혼공학습단⏰ (18)
        • 코드트리 챌린지👊🏻 (2)
        • 개발도서 100독👟 (8)
        • 나는 리뷰어다🌾 (11)
      • ◈ 자격증 공부 (37)
        • 정보처리기사🔱 (16)
        • 정보처리산업기사🔅 (9)
        • 컴퓨터활용능력 1급📼 (12)
      • ─────────── (0)
      • ◐ 기타 (113)
        • 알아두면 좋은 팁(tip)✨ (46)
        • 개발자의 일상🎈 (44)
        • 개발도서 서평🔍 (10)
        • 개발관련 세미나🎤 (2)
        • 블로그 꾸미기🎀 (9)
        • 사도신경 프로젝트🎚️ (2)
  • 인기 글

  • 최근 댓글

  • 태그

    자바스크립트
    SQL
    프로그래밍
    jsp
    꿀팁
    코딩 테스트
    코딩
    Project
    일상
    html
    Database
    BOJ
    spring
    Error Note
    Oracle
    CSS
    javascript
    백준
    Java
    백준 티어
  • 250x250
  • hELLO· Designed By정상우.v4.10.3
예르미(yermi)
[GoF] Strategy 패턴 : 알고리즘을 모두 바꾼다 [같은 문제를 다른 방법으로 해결하기 쉽게 만들어주는 패턴]
상단으로

티스토리툴바