接上一篇文章
【面向对象课程项目:纸牌】Java实例学习(一):优秀源码的分析
在看了上面优秀的源码之后,我开始反思为什么自己的代码 既不易于维护,也不易于加壳.到现在使用JAVAX的时候,自己还是在为那些跳不完的莫名其妙的swing方面的bugs苦恼.(考虑过自己曾经在设计的时候,根本就没有考虑过要加上图形界面的想法,但是这样始终不能算作一个理由--"别看我识字不多!懒和穷永远是一个字!"-).虽然遵循了MVC的开发思路,但是始终没有走出"想到哪儿写到哪儿的思路".这样不仅在效率上会受到严重的影响,而且一旦要在原有的基础上扩展,或让整个程序的代码变得越来越笨拙.最后走向瘫痪.而且实际上除了将函数给封装到类的内部,自己没有做出其他方面 面向对象的 使用,其实质 背离了学院开设 课程的初衷.
这是一个很好的例子,自己在代码中的错误,希望后人不要再犯,前人不要鄙夷;希望能够让闪光点和优秀的习惯得以保留,而那些坏的编码还有不良的习惯会慢慢的减少,消失,从而一点点成长,一点点蜕变.
一.自己模型的内涵
- 先看看自己的类设计:CardSetting类,这个是自己写单机版的黑白棋的时候保留下的一个习惯,将函数的资源和 常量属性给放到一个静态类中.这样的好处是能够集中调试,配置管理,同时也增加了代码的可复用性.但是由于 各个常量没有放在对应被使用的类中,会造成引用时不直观的缺点.源码如下:
package com.Cards.model; /** * @author Rock Lee * */ public class CardSetting { final public static int CARD_COUNT=13; final public static int INDEX_HEART=0;//红桃的角标 ♠ final public static int INDEX_SPADE=1;//黑桃的 角标♥ final public static int INDEX_DIAMOND=2;//方片的角标 ♦ final public static int INDEX_CLUB=3;//草花的角标 ♣ //final public static String[] COLOR={"HEART ♥","SPADE ♠","DIAMOND ♦","CLUB ♣"}; final public static String[] COLOR={"♥","♠","♦","♣"}; final public static String[] NUM={"A","2","3","4","5","6","7","8","9","10","J","Q","K"}; }
可以看到,使用角标来表示,是为了让代码变得易读,但是倘若能够查阅到此源码,上面的几个index就不该要,反而更清晰 - 接下来看基本的Card模型: 属性冗余较多,而且在CardSetting.java中不雅的编码方式影响了构造方法中的阅读性
package com.Cards.model; /** * @author Rock Lee * @version 2012-10-21 16:51:49 * @see CardSetting.java * @proposal Build A Class Contain All the info for ONE Card in the poker * @fix 2012-12-12 13:01:04 * */ public class Card { private String color = null; private String num = null; private boolean visible = false; private boolean red = false; public Card(String color, String num) { this.color = color; this.num = num; // if the color is diamond or heart ,then red is true,else false if (color.equals(CardSetting.COLOR[CardSetting.INDEX_HEART]) || color.equals(CardSetting.COLOR[CardSetting.INDEX_DIAMOND])) this.red = true; else this.red = false; } /* * 若花色,牌面大小相同,则认为是同一张牌 * */ public boolean equals(Object obj) { Card anotherCard = (Card) obj; return this.color.equals((anotherCard.color)) && this.num.equals(anotherCard.num); } public void setVisiable(boolean visible) { this.visible = visible; } public boolean isVisible() { return visible; } public boolean isRed() { return red; } /* * 1.此方法仅用于 命令行,或调试模式中2.重载了 object的使用方法.在整个列,或者deck suit输出的时候,方便 以字符串的方式拼接 */ public String toString() { if (this == null) return "EMPTY"; else { if (this.isVisible()) { return (color + " " + num + " "); } else return "███ "; } } public String getColor() { return color; } /* 以数字的方式,返回牌面的大小 */ public int getNum() { char ch = num.charAt(0); switch (ch) { case 'A': return 1; case 'J': return 11; case 'Q': return 12; case 'K': return 13; default: return Integer.parseInt(num); } } /* 以String的方式,返回牌面的大小 */ public String getNumInString() { return num; } }
- 不得不说,在简化问题的时候,自己仍然没有细看题目要求,为了方便设计,老师将题目中的deck 和discard已经分开画了.而且这张图也说明了discard只需要展示一张牌,不需要考虑像win纸牌中三张牌的叠加排放.
- 接下来看看自己实现的几个坑爹的数据结构,分别为CardDeck,CardHeap,CardList,CardStack(这个本应该命名为CardSuit的)
- CardHeap类
package com.Cards.model; import java.util.Vector; /** * @author Rock Lee * @version 2012-10-21 17:04:34 * @proposal Support the initialization for the whole set of poker,and the Cards left on the DECK * */ public class CardHeap { //这里使用了vector来维护一套 "刚刚从扑克牌盒子里取出的 52张牌" private Vector<Card> vector=null; public CardHeap() { this.initialize(); } /*初始化13*4=52张牌*/ public void initialize() { vector=new Vector<Card>(); Card tmp=null; for (int i = 0; i < 13; i++)//13 cards in Color Heart { tmp=new Card(CardSetting.COLOR[CardSetting.INDEX_HEART], CardSetting.NUM[i]); tmp.setVisiable(false); vector.add(tmp); } for (int i = 0; i < 13; i++)//13 cards in Color SPADE { tmp=new Card(CardSetting.COLOR[CardSetting.INDEX_SPADE], CardSetting.NUM[i]); tmp.setVisiable(false); vector.add(tmp); } for (int i = 0; i < 13; i++)//13 cards in Color DIAMOND { tmp=new Card(CardSetting.COLOR[CardSetting.INDEX_DIAMOND], CardSetting.NUM[i]);
- CardHeap类