템플릿 방법과 전략 결합


14

내 소프트웨어 엔지니어링 수업에서 과제는 특정 게임에서 다른 형태를 재생할 수있는 응용 프로그램을 설계하는 것입니다. 문제의 게임은 Mancala이며,이 게임 중 일부는 Wari 또는 Kalah라고합니다. 이러한 게임은 몇 가지 측면에서 차이가 있지만 내 질문에 따르면 다음과 같은 경우 게임이 다를 수 있음을 아는 것만 중요합니다.

  • 이동 결과가 처리되는 방식
  • 게임의 끝을 결정하는 방법
  • 승자가 결정되는 방식

이것을 설계하기 위해 가장 먼저 생각한 것은 전략 패턴을 사용하는 것이 었습니다. 알고리즘 (게임의 실제 규칙)에 변형이 있습니다. 디자인은 다음과 같습니다. 여기에 이미지 설명을 입력하십시오

나는 Mancala와 Wari 게임에서 승자가 결정되는 방식이 정확히 동일하고 코드가 복제 될 것이라고 스스로 생각했다. 나는 이것이 정의에 의해 '하나의 규칙, 한 곳'또는 DRY 원칙을 위반한다고 Mancala에 대한 규칙의 변경으로 보는 것이 Wari에서도 규칙이 변경되어야한다는 것을 자동으로 의미하지는 않는다고 생각하지 않습니다. 그럼에도 불구하고 교수로부터받은 피드백을 통해 다른 디자인을 찾을 수 있다는 인상을 받았습니다.

그런 다음 이것을 생각해 냈습니다. 여기에 이미지 설명을 입력하십시오

각 게임 (Mancala, Wari, Kalah, ...)은 각 규칙의 인터페이스 유형의 속성을 가지게됩니다. 즉 WinnerDeterminerMancala 1.0과 동일한 Mancala 2.0 버전이있는 경우 승자가 결정되는 방법을 제외하고는 Mancala 버전을 사용하십시오.

전략 패턴으로 이러한 규칙을 구현하는 것이 확실히 유효하다고 생각합니다. 그러나 실제 문제는 더 디자인하려고 할 때 발생합니다.

템플릿 메소드 패턴에 대해 읽었을 때 즉시이 문제에 적용될 수 있다고 생각했습니다. 사용자가 움직일 때 수행되는 작업은 항상 동일하며 동일한 순서로 다음과 같습니다.

  • 구멍에 돌을 입금하십시오 (모든 게임에서 동일하므로 템플릿 방법 자체로 구현됩니다)
  • 이동 결과 결정
  • 이전 이동으로 인해 게임이 완료되었는지 확인
  • 게임이 끝나면 누가 이겼는지 결정하십시오

마지막 세 단계는 모두 위에서 설명한 전략 패턴에 있습니다. 이 두 가지를 결합하는 데 많은 어려움이 있습니다. 내가 찾은 가능한 해결책 중 하나는 전략 패턴을 포기하고 다음을 수행하는 것입니다. 여기에 이미지 설명을 입력하십시오

전략 패턴과 이것의 디자인 차이가 실제로 보이지 않습니까? 그러나 템플릿 방법을 사용해야한다고 확신합니다 (전략 패턴을 사용해야한다고 확신하더라도).

또한 누가 TurnTemplate객체 생성을 담당 할 것인지 결정할 수 없지만 전략 패턴을 사용하면 추상 팩토리 패턴을 사용하여 쉽게 생성 할 수있는 객체 패밀리 (세 가지 규칙)가 있다고 생각합니다. 나는 다음을 것 MancalaRuleFactory, WariRuleFactory등 그리고 그들은 나를 다시 규칙과 손의 올바른 인스턴스 생성 할 RuleSet객체를.

전략 + 추상 팩토리 패턴 RuleSet을 사용하고 세 가지 규칙에 대한 알고리즘 이있는 객체 가 있다고 가정 해 봅시다 . 이 방법으로 템플릿 메소드 패턴을 계속 사용할 수 있다고 생각하는 유일한 방법은이 RuleSet객체를 my 에 전달 하는 것 TurnTemplate입니다. 그때 나타나는 '문제'는 구체적인 구현이 필요하지 않다는 것입니다 TurnTemplate.이 클래스는 더 이상 사용되지 않습니다. 에서 보호 된 메소드에서 TurnTemplate전화를 걸 수 있습니다 ruleSet.determineWinner(). 결과적으로 TurnTemplate클래스는 더 이상 추상적이지 않지만 구체적이어야하는데 여전히 템플릿 메소드 패턴입니까?

요약하면, 올바른 방법으로 생각하고 있습니까, 아니면 쉬운 것을 놓치고 있습니까? 올바른 길을 가고 있다면 전략 패턴과 템플릿 방법 패턴을 어떻게 결합합니까?


1
나는 당신의 생각이 꽤 중요하다고 말하고 싶습니다. 교수로부터받은 피드백이 그 사실을 입증하지 못하면 결함을 지적하거나 답변에서 자신이 무엇을했는지 힌트를 주도록 요청하십시오. 마음을 읽으려고하지 마십시오. 교수 (및 나중에 사용자)가 원하는 것에 대해 가정하면 최악의 상황 일 수 있습니다.
Marjan Venema

" ... Mancala와 Wari 게임에서 승자가 결정되는 방식은 정확히 동일하며 코드는 복제 될 것입니다. "이것이 코드가 복제되었음을 의미하는 이유는 무엇입니까? 두 클래스가 동일한 함수를 호출하도록하십시오.
D Drmmr

답변:


6

디자인을 살펴본 후 첫 번째와 세 번째 반복 모두 더 우아한 디자인으로 보입니다. 그러나 당신은 당신이 학생이고 교수가 당신에게 피드백을 주었다고 언급했습니다. 당신의 과제 나 수업의 목적이 무엇인지 또는 교수가 제안한 것에 대한 더 많은 정보를 정확히 알지 못한다면, 나는 소금 한 알로 아래에서 말하는 것을 취할 것입니다.

첫 번째 디자인에서는 RuleInterface각 플레이어의 차례를 처리하는 방법, 게임이 끝났는지 확인하는 방법 및 게임이 끝난 후 승자를 결정하는 방법을 정의하는 인터페이스가되도록 선언합니다 . 변형을 경험하는 게임 제품군에 대한 유효한 인터페이스 인 것 같습니다. 그러나 게임에 따라 코드가 중복되었을 수 있습니다. 한 게임의 규칙을 변경할 수있는 유연성은 좋은 일이지만, 코드 복제가 결함으로 인해 끔찍하다고 주장합니다. 구현간에 결함이있는 코드를 복사 / 붙여넣고 버그가있는 경우 이제 다른 위치에서 수정해야하는 여러 버그가 있습니다. 다른 시간에 구현을 다시 작성하면 다른 위치에 결함이 발생할 수 있습니다. 이들 중 어느 것도 바람직하지 않습니다.

두 번째 디자인은 깊은 상속 트리로 다소 복잡해 보입니다. 적어도 이런 유형의 문제를 해결하기 위해 기대했던 것보다 더 깊습니다. 또한 구현 세부 사항을 다른 클래스로 나누기 시작했습니다. 궁극적으로 게임을 모델링하고 구현합니다. 언급 한 요구 사항에없는 것으로 보이는 이동 결과, 게임 종료 및 승자 결정을위한 규칙을 믹스 앤 매치해야하는 경우 흥미로운 접근 방법입니다. . 귀하의 게임은 잘 정의 된 규칙 세트이며, 가능한 한 개별 엔터티로 게임을 캡슐화하려고합니다.

세 번째 디자인은 내가 가장 좋아하는 디자인입니다. 나의 유일한 관심사는 그것이 올바른 추상화 수준에 있지 않다는 것입니다. 지금 당신은 턴을 모델링하고있는 것 같습니다. 게임 디자인을 고려하는 것이 좋습니다. 돌을 사용하여 어떤 종류의 보드에서 움직임을 만드는 플레이어가 있다고 가정하십시오. 당신의 게임에는이 배우들이 있어야합니다. 거기에서 알고리즘은가 doTurn()아니라 playGame()초기 이동에서 최종 이동으로 이동 한 후 종료됩니다. 모든 플레이어의 움직임이 끝나면 게임 상태를 조정하고 게임이 최종 상태인지 여부를 결정하고, 그렇지 않은 경우 승자를 결정합니다.

첫 번째와 세 번째 디자인을 자세히 살펴보고 함께 작업하는 것이 좋습니다. 프로토 타입 측면에서 생각하는 것도 도움이 될 수 있습니다. 이러한 인터페이스를 사용하는 클라이언트는 어떤 모습입니까? 실제로 게임을 인스턴스화하고 게임을하는 클라이언트를 구현하는 데 하나의 디자인 방식이 더 합리적입니까? 상호 작용하는 것을 알아야합니다. 특별한 경우에는 Game클래스 및 기타 관련 요소이므로 별도로 디자인 할 수 없습니다.


당신이 학생이라고 언급 했으므로 소프트웨어 디자인 과정의 TA 였을 때부터 몇 가지를 공유하고 싶습니다.

  • 패턴은 단순히 과거에 일한 것들을 캡처하는 방법이지만 다른 디자인에서 사용할 수있는 지점으로 추상화합니다. 각 디자인 패턴 카탈로그는 패턴의 이름을 지정하고, 의도와 사용 가능한 위치 및 궁극적으로 디자인을 제한하는 상황을 설명합니다.
  • 디자인은 경험과 함께 제공됩니다. 디자인을 잘 활용하는 가장 좋은 방법은 단순히 모델링 측면에만 초점을 두는 것이 아니라 해당 모델 구현에 어떤 영향을 미치는지 이해하는 것입니다. 가장 우아한 디자인은 쉽게 구현할 수 없거나 더 큰 시스템 디자인이나 다른 시스템에 맞지 않는 경우에 유용합니다.
  • "올바르거나"잘못된 디자인은 거의 없습니다. 디자인이 시스템의 요구 사항을 충족하는 한 잘못 될 수 없습니다. 각 요구 사항에서 시스템이 해당 요구 사항을 어떻게 충족 시킬지에 대한 표현으로 매핑되면 디자인이 잘못 될 수 없습니다. 이 시점에서 유연성 또는 재사용 성 또는 테스트 가능성 또는 유지 관리 성과 같은 개념에 대해서는 질적입니다.

훌륭한 조언, 특히 잘못된 추상화 레벨에 있다는 사실에 대한 귀하의 요점에 감사드립니다. 나는 지금 그것을 GameTemplate훨씬 나아지 는 것으로 바꿨습니다 . 또한 플레이어, 보드 등을 초기화하는 팩토리 메소드를 결합 할 수 있습니다.
Mekswoll

3

당신의 혼란은 정당합니다. 문제는 패턴이 상호 배타적이지 않다는 것입니다.

템플릿 방법은 전략 및 상태와 같은 여러 다른 패턴의 기초입니다. 기본적으로 전략 인터페이스에는 전략을 구현하는 모든 객체가 최소한 doAction () 메소드와 같은 것을 갖도록 요구하는 하나 이상의 템플릿 메소드가 포함됩니다. 이를 통해 전략을 서로 대체 할 수 있습니다.

Java에서 인터페이스는 템플릿 메소드 집합 일뿐입니다. 마찬가지로, 추상적 인 방법은 본질적으로 템플릿 방법입니다. 이 패턴 (다른 것들 중에서도)은 언어 디자이너들에게 잘 알려져 있었기 때문에 언어를 내장했습니다.

@ThomasOwens는 특정 문제에 대한 훌륭한 조언을 제공합니다.


0

디자인 패턴에주의가 산만하다면 게임을 먼저 프로토 타입하는 것이 좋을 것입니다. 시스템을 완벽하게 먼저 디자인하고 구현하는 것이 실제로 가능하거나 바람직하지 않다고 생각합니다 (유사한 방법으로 사람들이 전체 프로그램을 먼저 작성한 다음 컴파일하는 것이 조금씩 복잡 해짐) .) 문제는 로직이 처리해야 할 모든 시나리오를 생각할 것 같지 않으며 구현 단계에서 모든 희망을 잃거나 원래의 결함이있는 디자인을 고수하고 해킹을 도입하려고 시도하거나 심지어는 더 나쁜 것은 전혀 제공하지 않습니다.


2
일반적으로 나는 당신에게 동의 하지만 이것은 실제로 OP의 문제를 해결하는 답이 아닙니다. "하지 마라"는 대답이지만, 가능한 대안을 제공하지 않으면 다소 열악한 것입니다.
yannis

@YannisRizos 그리고 나는 당신 에게도 동의하지만 , 나는 여전히 그가 건전한 조언 (또는 조언이 옳지 않은 경우 통찰력)을했다고 생각합니다. 이런 이유로 +1. 그럼에도 불구하고 기술적으로 매우 유용한 답변 은 아닙니다 .
777을 10:29에 구입 함

-1

황동 압정으로 넘어 가자. 게임 인터페이스, 디자인 패턴, 추상 클래스 및 UML이 전혀 필요하지 않습니다.

UI, 시뮬레이션 등과 같은 합리적인 수준의 지원 클래스가 있다면 기본적으로 게임 로직이 아닌 모든 코드가 재사용됩니다. 또한 사용자는 게임을 동적으로 변경하지 않습니다. 게임간에 30Hz로 뒤집지 않습니다. 약 30 분 동안 한 게임을합니다. 따라서 "동적"다형성은 실제로 동적이 아닙니다. 다소 정적입니다.

따라서 여기에 현명한 방법은 C # Action또는 C ++ 와 같은 일반적인 기능 추상화를 사용하고 std::function하나의 Mancala, 하나의 Wari 및 하나의 Kalah 클래스를 만든 다음 거기에서 이동하는 것입니다.

std::unordered_map<std::string, std::function<void()>> games = {
    { "Kalah", [] { return Kalah(); } },
    { "Mancala", [] { return Mancala(); } },
    { "Wari", [] { return Wari(); } }
};
void play() {
    std::function<void()> f;
    f = games[GetChoiceFromUI()];
    f();
    if (PlayAgain()) return play();
}
int main() {
    play();
}

끝난.

당신은 게임을 부르지 않습니다. 게임이 당신을 부릅니다.


3
이것이 어떻게 도움이되는지 모르겠습니다. 이 질문을하는 사람은 학생입니다. 그는 설계 원칙과 두 설계 패턴 간의 상호 작용에 대해 명시 적으로 묻고 있습니다. 디자인 패턴이 필요하지 않거나 UML이 일부 산업에서는 사실 일 수 있지만 디자인 모델, 디자인 패턴 및 UML에 대한 생각은 연습 문제가 될 수 있습니다.
토마스 오웬스

3
그들이 적용 할 곳이 없기 때문에 그들에 대해 할 말이 없습니다. 디자인 패턴을 사용하여 디자인을 사용하지 않는 방법에 대한 교훈이 아니라면 디자인 패턴을 사용하여 디자인을 완전히 구체화하는 방법에 대해 생각하는 데 시간이 걸리지 않습니다.
DeadMG

4
SoftDev에는 문제를 해결하는 것보다 사용 된 디자인 패턴이 더 중요한 것으로 간주되는 걱정스럽고 성가신 경향이 있습니다. 오버 엔지니어링과 같은 것이 있습니다.
James

2
@DeadMG : 둘 다 본질적으로 옳지 만 OP의 경우 문제가 시험을 통과하고 있으며 그 문제에 대한 해결책은 디자인 패턴과 UML을 사용하는 것입니다. 우리가 아무리 옳더라도, 그의 교수가 그의 해결책에 동의하지 않는다면 그는 통과하지 못할 것입니다.
Goran Jovic

2
모든 인생은 내가 항상 와우, "찌르기"이 방법이 더 의미가 ... "황동 세금"이라고 생각했습니다. lol
777
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.