如何避免使用属性“填充”泛型类?

时间:2010-12-01 15:52:58

标签: oop class design-patterns generics

我正在尝试将扑克游戏转换为正确的OOP模型 基础知识:

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

我从文本文件中获取游戏和手牌。我解析了几次文本文件,原因如下:

  • 获取一些信息(原因1)
  • 计算一些统计数据(原因2)
  • ...

由于原因1,我需要Hand类中的一些属性(a1,b1)。由于原因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:策略模式是锤子,不是吗?

*编辑 * 这是一个应用程序:

// 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 = ...  
    }  
} 

1 个答案:

答案 0 :(得分: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课程(尽可能多地保留OO),你应该避免将手伸向特定的手课。

** 更新 **

好吧,为了回答你的原始问题( sig ),班级Hand用于操纵和处理“手”。如果你需要计算其他统计数据或其他需求,包装你的Hand类可能不是一个好主意,因为你最终会得到一个复合类,这是不可取的(为了可维护性和OOP范例)。 / p>

原因1,正如责任链所示,拥有不同种类的手是可以的;你可以阅读你的文件,根据需要使用许多参数创建不同类型的牌。

由于原因2,您可以查看其他解决方案。一个是让你的Hand类触发事件(例如:当它被识别时),你的应用程序可以将这些手注册到其他类来监听事件。另一个班级也应负责从您正在阅读的文件中收集必要的数据。由于手不是(或不应该)负责收集统计数据,所以底线是您需要处理其他内容。

一个包 =连贯的API和功能

一个类 =连贯的功能(一只手是一只手,而不是一个统计容器)

一种方法 =一种(单一)功能(如果方法需要处理多个功能,将这些功能分解为单独的私有方法,并从公共方法中调用它们)

我在这里给你一个通用的答案,因为原因1 原因2 并不具体。