2010-12-01 1 views
0

Я пытаюсь перевести покерную игру в правильную модель ООП.
Основы:Как избежать «заполнения» класса с атрибутами?

class Hand 
{ 
    Card cards[]; 
} 
class Game 
{ 
    Hand hands[]; 
} 

Я получаю игры и руки из текстового файла. Я анализирую в текстовый файл несколько раз, по нескольким причинам:

  • прибудете Somes INFOS (причина 1)
  • вычислить некоторые статистические данные (причина 2)
  • ...

По причине 1 Мне нужны некоторые атрибуты (a1, b1) в классе Hand. По причине 2 мне нужны некоторые другие атрибуты (a2, b2). Я думаю, что грязный способ будет:

class Hand 
{ 
    Card cards[]; 
    Int a1,b1; 
    Int a2,b2; 
} 

Я имею в виду, что бы некоторые атрибуты бесполезны большую часть времени. Таким образом, чтобы быть чище, мы могли бы сделать:

class Hand 
{ 
    Card cards[]; 
} 
class HandForReason1 extends Hand 
{ 
    Int a1,b1; 
} 

Но я чувствую, что с помощью молотка ...

Мой вопрос: есть ли промежуточный путь? Или молотковое решение хорошее? (в этом случае, что было бы правильной семантикой?)

PS: шаблоны дизайна приветствуются :-)
PS2: шаблон стратегии - это молот, не так ли?

* EDIT * Вот это приложение:

// Parse the file, read game infos (reason 1) 
// Hand.a2 is not needed here ! 
class Parser_Infos 
{ 
    Game game; 
    function Parse() 
    { 
      game.hands[0].a1 = ... 
    } 
} 
// Later, parse the file and get some statistics (reason 2) 
// Hand.a1 is not needed here ! 
class Parser_Stats 
{ 
    Game game; 
    function Parse() 
    { 
     game.hand[0].a2 = ... 
    } 
} 
+0

Рука, форматирующая ваше сообщение с помощью html, будет работать более или менее, вам будет проще и быстрее использовать механизм уценки, предоставляемый Stack Overflow. [Редактирование страницы справки] (http://stackoverflow.com/editing-help). – dmckee 2010-12-01 16:09:08

+0

Я думаю, нам будет намного легче понять вашу проблему, если вы используете пример реальной жизни для ваших «атрибутов». Что означают значения a1 и b1, a2 и b2? – Fortega 2010-12-01 16:29:04

ответ

0

Используя цепочку ответственности признать покер рука, что я буду делать. Поскольку каждая рука имеет свои собственные характеристики, вы не можете просто иметь общую руку.

Что-то вроде

abstract class Hand { 
    protected Hand next; 

    abstract protected boolean recognizeImpl(Card cards[]); 

    public Hand setNext(Hand next) { 
     this.next = next; 
     return next; 
    } 

    public boolean Hand recognize(Card cards[]) { 
     boolean result = ; 
     if (recognizeImpl(cards)) { 
     return this; 
     } else if (next != null) { 
     return next.recognize(cards); 
     } else { 
     return null; 
     } 
    } 
} 

а затем ваша реализация

class FullHouse extends Hand { 
    protected boolean recognizeImpl(Card cards[]) { 
     //... 
    } 
} 
class Triplet extends Hand { 
    protected boolean recognizeImpl(Card cards[]) { 
     //... 
    } 
} 

Затем построить свою цепь

// chain start with "best" hand first, we want the best hand 
// to be treated first, least hand last 
Hand handChain = new FullHouse(); 
handChain 
    .setNext(new Triplet()) 
    //.setNext(...)  /* chain method */ 
; 

//... 

Hand bestHand = handChain.recognize(cards); 
if (bestHand != null) { 
    // The given cards correspond best to bestHand 
} 

Кроме того, с каждой стороны это собственный класс, вы можете инициализировать и иметь затем удерживайте и вычисляйте очень конкретные вещи. Но так как вы должны манипулировать Hand классами столько, сколько сможете (чтобы остаться как можно больше ОО), вам не следует бросать руки в определенный ручной класс.

** UPDATE **

Хорошо, так, чтобы ответить на исходный вопрос (сиг) класс Hand для манипулирования и лечения "руки".Если вам нужно рассчитать другие статистические данные или другие потребности, упаковка вашего класса Hand может быть не очень хорошей идеей, так как вы получите сложный класс, что нежелательно (для удобства обслуживания и парадигмы ООП).

По этой причине 1, все в порядке, чтобы иметь разные виды рук, как иллюстрирует цепочка ответственности; вы можете прочитать свой файл, создать различные виды рук с множеством параметров, как это требуется.

По причине 2, вы можете посмотреть другие решения. Можно было бы, чтобы ваши события Hand загорелись (например: когда они были распознаны), и ваше приложение могло зарегистрировать эти руки в каком-то другом классе для прослушивания событий. Этот класс также должен отвечать за сбор необходимых данных из файлов, которые вы читаете. Поскольку рука не (или не должна) нести ответственность за сбор статистических данных, нижняя строка заключается в том, что вам нужно иметь что-то другое, чтобы справиться с этим.

Один пакет = когерентное API, и функциональные возможности

Один класс = когерентные функциональные (рука является рукой, не статистический контейнер)

Один метод = а (одиночный) функциональность (если метод должен обрабатывать более одной функциональности, разбить эти функции на отдельные частные методы и вызвать их из общедоступного метода)

Я - giv вы здесь общий ответ, потому что причина 1 и причина 2 не являются конкретными.

Смежные вопросы