Java 卡片组的面向对象设计——如何使未来拥有更多卡片变得灵活

Java 卡片组的面向对象设计——如何使未来拥有更多卡片变得灵活,java,oop,design-patterns,object,Java,Oop,Design Patterns,Object,假设我们有一副卡片的面向对象设计,如中所示 从URL复制,这里是完整的卡片类 它足够通用,可以高度重用,因此设计、编写和测试它所做的工作从长远来看会获得丰厚的回报 /** *类型为Card的对象表示来自 *标准扑克牌组,包括小丑。这张卡片上有一套衣服,这套衣服 *可以是黑桃、红桃、钻石、梅花或小丑。一把铁锹,一颗心, *钻石或俱乐部有13种价值观之一:A、2、3、4、5、6、7、, *8、9、10、杰克、女王或国王。注意,“ace”被认为是 *最小值。小丑也可以有关联的值; *此值可以是任何值,

假设我们有一副卡片的面向对象设计,如中所示

从URL复制,这里是完整的卡片类

它足够通用,可以高度重用,因此设计、编写和测试它所做的工作从长远来看会获得丰厚的回报

/**
*类型为Card的对象表示来自
*标准扑克牌组,包括小丑。这张卡片上有一套衣服,这套衣服
*可以是黑桃、红桃、钻石、梅花或小丑。一把铁锹,一颗心,
*钻石或俱乐部有13种价值观之一:A、2、3、4、5、6、7、,
*8、9、10、杰克、女王或国王。注意,“ace”被认为是
*最小值。小丑也可以有关联的值;
*此值可以是任何值,并可用于跟踪多个值
*不同的小丑。
*/
公务舱卡{
public final static int SPADES=0;//四套西装的代码,加上小丑。
公共最终静态整数=1;
公共最终静态整数钻石=2;
公共最终静态积分俱乐部=3;
公开决赛静态整容小丑=4;
public final static int ACE=1;//非数字卡的代码。
public final static int JACK=11;//卡2到卡10具有
public final static int QUEEN=12;//其代码的数值。
公共最终静态int KING=13;
/**
*这张卡的套装,黑桃,红桃,钻石,
*球杆,或小丑。卡被打开后,西装不能更换
*建造的。
*/
私人最终诉讼;
/**
*卡的值。对于普通卡,这是一个值
*1到13,其中1表示a。对于小丑,值为
*可以是任何内容。卡后不能更改值
*是建造的。
*/
私有最终整数值;
/**
*创建一个小丑,关联值为1。(注意
*“new Card()”相当于“new Card(1,Card.JOKER)”
*/
公共卡(){
西装=小丑;
数值=1;
}
/**
*创建具有指定套色和值的卡。
*@param theValue新卡的值。对于普通卡(非小丑卡),
*该值必须在1到13之间,1表示Ace。
*您可以使用常量Card.ACE、Card.JACK、Card.QUEEN和Card.KING。
*对于一个小丑来说,价值可以是任何东西。
*@param适合新卡的套装。这必须是其中一个值
*卡。黑桃,卡。红桃,卡。钻石,卡。梅花,或卡。小丑。
*如果参数值不在
*允许范围
*/
公共卡(内部价值,内部诉讼){
如果(西服)=黑桃和西服!=红桃和西服!=钻石和
西服!=俱乐部和西服!=小丑)
抛出新的非法辩论例外(“非法扑克牌套装”);
if(theSuit!=小丑&(theValue<1 | | theValue>13))
抛出新的IllegalArgumentException(“非法扑克牌值”);
价值=价值;
西服=西服;
}
/**
*退回这张卡的套装。
*@返回一套衣服,这是卡牌中的一种,
*卡片。红心,卡片。钻石,卡片。梅花,或卡片。小丑
*/
公共int getSuit(){
反诉;
}
/**
*返回此卡的值。
*@返回值,该值是数字1到13中的一个,包括
*一张普通的卡片,对小丑来说可以是任何价值。
*/
public int getValue(){
返回值;
}
/**
*返回卡的套装的字符串表示形式。
*@返回其中一个字符串“黑桃”、“红桃”、“钻石”、“梅花”
*或“小丑”。
*/
公共字符串getSuiteAsString(){
开关(套装){
案例黑桃:返回“黑桃”;
案例红心:返回“红心”;
案例钻石:返回“钻石”;
案例俱乐部:返回“俱乐部”;
默认值:返回“小丑”;
}
}
/**
*返回卡值的字符串表示形式。
*@return为普通卡,字符串“Ace”、“2”之一,
*“3”、“10”、“杰克”、“女王”或“国王”。对于小丑来说
*字符串总是数字。
*/
公共字符串getValueAsString(){
如果(西装=小丑)
返回“”+值;
否则{
开关(值){
案例1:返回“Ace”;
案例2:返回“2”;
案例3:返回“3”;
案例4:返回“4”;
案例5:返回“5”;
案例6:返回“6”;
案例7:返回“7”;
案例8:返回“8”;
案例9:返回“9”;
案例10:返回“10”;
案例11:返回“Jack”;
案例12:返回“女王”;
默认:返回“国王”;
}
}
}
/**
*返回此卡的字符串表示形式,包括
*它的西装和价值(价值为1的小丑除外,
*返回值只是“小丑”)。示例返回值
*是:“红心皇后”、“钻石之十”、“黑桃王牌”,
*“小丑”,“小丑2”
*/
公共字符串toString(){
如果(西装=小丑){
如果(值==1)
返回“小丑”;
其他的
返回“小丑”+值;
}
其他的
返回“+GetSuiteAsString()的getValueAsString()+”;
}
}//末级卡

假设我想在这个设计中包括两个小丑,而不干扰当前的类,如何实现这一点?

类中,一个构造函数是
(值,套装)
。小丑被定义为一种卡片组合。您可以指定要跟踪小丑的任何值

类的默认构造函数创建一个小丑

您可以通过在套装和值中添加新的
最终静态int
值来定义您想要的任何其他卡。

小丑应该是
/**
 * An object of type Card represents a playing card from a
 * standard Poker deck, including Jokers.  The card has a suit, which
 * can be spades, hearts, diamonds, clubs, or joker.  A spade, heart,
 * diamond, or club has one of the 13 values: ace, 2, 3, 4, 5, 6, 7,
 * 8, 9, 10, jack, queen, or king.  Note that "ace" is considered to be
 * the smallest value.  A joker can also have an associated value; 
 * this value can be anything and can be used to keep track of several
 * different jokers.
 */

public class Card {

   public final static int SPADES = 0;   // Codes for the 4 suits, plus Joker.
   public final static int HEARTS = 1;
   public final static int DIAMONDS = 2;
   public final static int CLUBS = 3;
   public final static int JOKER = 4;

   public final static int ACE = 1;      // Codes for the non-numeric cards.
   public final static int JACK = 11;    //   Cards 2 through 10 have their 
   public final static int QUEEN = 12;   //   numerical values for their codes.
   public final static int KING = 13;

   /**
    * This card's suit, one of the constants SPADES, HEARTS, DIAMONDS,
    * CLUBS, or JOKER.  The suit cannot be changed after the card is
    * constructed.
    */
   private final int suit; 

   /**
    * The card's value.  For a normal card, this is one of the values
    * 1 through 13, with 1 representing ACE.  For a JOKER, the value
    * can be anything.  The value cannot be changed after the card
    * is constructed.
    */
   private final int value;

   /**
    * Creates a Joker, with 1 as the associated value.  (Note that
    * "new Card()" is equivalent to "new Card(1,Card.JOKER)".)
    */
   public Card() {
      suit = JOKER;
      value = 1;
   }

   /**
    * Creates a card with a specified suit and value.
    * @param theValue the value of the new card.  For a regular card (non-joker),
    * the value must be in the range 1 through 13, with 1 representing an Ace.
    * You can use the constants Card.ACE, Card.JACK, Card.QUEEN, and Card.KING.  
    * For a Joker, the value can be anything.
    * @param theSuit the suit of the new card.  This must be one of the values
    * Card.SPADES, Card.HEARTS, Card.DIAMONDS, Card.CLUBS, or Card.JOKER.
    * @throws IllegalArgumentException if the parameter values are not in the
    * permissible ranges
    */
   public Card(int theValue, int theSuit) {
      if (theSuit != SPADES && theSuit != HEARTS && theSuit != DIAMONDS && 
            theSuit != CLUBS && theSuit != JOKER)
         throw new IllegalArgumentException("Illegal playing card suit");
      if (theSuit != JOKER && (theValue < 1 || theValue > 13))
         throw new IllegalArgumentException("Illegal playing card value");
      value = theValue;
      suit = theSuit;
   }

   /**
    * Returns the suit of this card.
    * @returns the suit, which is one of the constants Card.SPADES, 
    * Card.HEARTS, Card.DIAMONDS, Card.CLUBS, or Card.JOKER
    */
   public int getSuit() {
      return suit;
   }

   /**
    * Returns the value of this card.
    * @return the value, which is one of the numbers 1 through 13, inclusive for
    * a regular card, and which can be any value for a Joker.
    */
   public int getValue() {
      return value;
   }

   /**
    * Returns a String representation of the card's suit.
    * @return one of the strings "Spades", "Hearts", "Diamonds", "Clubs"
    * or "Joker".
    */
   public String getSuitAsString() {
      switch ( suit ) {
      case SPADES:   return "Spades";
      case HEARTS:   return "Hearts";
      case DIAMONDS: return "Diamonds";
      case CLUBS:    return "Clubs";
      default:       return "Joker";
      }
   }

   /**
    * Returns a String representation of the card's value.
    * @return for a regular card, one of the strings "Ace", "2",
    * "3", ..., "10", "Jack", "Queen", or "King".  For a Joker, the 
    * string is always numerical.
    */
   public String getValueAsString() {
      if (suit == JOKER)
         return "" + value;
      else {
         switch ( value ) {
         case 1:   return "Ace";
         case 2:   return "2";
         case 3:   return "3";
         case 4:   return "4";
         case 5:   return "5";
         case 6:   return "6";
         case 7:   return "7";
         case 8:   return "8";
         case 9:   return "9";
         case 10:  return "10";
         case 11:  return "Jack";
         case 12:  return "Queen";
         default:  return "King";
         }
      }
   }

   /**
    * Returns a string representation of this card, including both
    * its suit and its value (except that for a Joker with value 1,
    * the return value is just "Joker").  Sample return values
    * are: "Queen of Hearts", "10 of Diamonds", "Ace of Spades",
    * "Joker", "Joker #2"
    */
   public String toString() {
      if (suit == JOKER) {
         if (value == 1)
            return "Joker";
         else
            return "Joker #" + value;
      }
      else
         return getValueAsString() + " of " + getSuitAsString();
   }


} // end class Card