类型码从int到对象的转变
最近在读代码重构的书。其中这点受益匪浅。记录一下。
取出魔法数,将其声明为final (static) 变量,非常经典的作法。
但不仅仅止步于此。其最致命的缺点就是:他只是一个整数。
那就意味着没有类型检查。尤其如类型,flag。
public static final int FLAG_ACTION_MOOD = FLAG_ACTION_DEFAULT; public static final int FLAG_ACTION_MOOD_WRONGED = FLAG_ACTION_DEFAULT; public static final int FLAG_ACTION_MOOD_CRY = 0x00020000; public static final int FLAG_ACTION_MOOD_PLEASANT = 0x00040000; //... public static final int FLAG_ACTION_MEAL_BREAKFAST = FLAG_ACTION_DEFAULT; public static final int FLAG_ACTION_MEAL_LUNCH = 0x00020000; public static final int FLAG_ACTION_MEAL_DINNER = 0x00040000; //...
如上面,这只是其中的一部分。难免会用错(本人比较马虎,常犯这种错误),会导致将错误推迟到运行时。
所以。将类型码从int转为Object. 就可以支持类型检查。就可以将错误提前到编译。
而且还可以利用最NB的工具。多态。来达到意想不到的效果。(比如可以将NULL融合进去)
原来的代码:
public class DateModel { public static final int UNKNOWN = 0; public static final int DAY = 1; public static final int WEEK = 2; public static final int MONTH = 3; }
重构后的代码:本人懒 直接贴源码了。
1 public abstract class DateModel { 2 public static final DateModel UNKNOWN = new DM_UNKNOWN(0); 3 public static final DateModel DAY = new DM_DAY(1); 4 public static final DateModel WEEK = new DM_WEEK(2); 5 public static final DateModel MONTH = new DM_MONTH(3); 6 7 public static final DateModel[] MODELS = new DateModel[] { 8 UNKNOWN, DAY, WEEK, MONTH}; 9 10 public static final DateModel getObject(int code) { return MODELS[code]; }; 11 12 private final int code; 13 14 private DateModel(int code) { this.code = code; } 15 16 public final int getCode() { return code; } 17 18 @Override 19 public boolean equals(Object o) { 20 return ((DateModel) o).code == code ? true : false; 21 } 22 23 @Override 24 public int hashCode() { 25 return 1 * 17 + code; 26 } 27 28 /** 29 * get previous time base on dateModel</br> 30 * <table> 31 * <tr><td>DATE_MODEL</td><td>RESULT</td></tr> 32 * <tr><td>DAY</td><td>Calendar.DATE -= 1</td></tr> 33 * <tr><td>WEEK</td><td>Calendar.WEEK_OF_MONTH -= 1</td></tr> 34 * <tr><td>MONTH</td><td>Calendar.MONTH -= 1</td></tr> 35 * </table> 36 * @param current 37 * @return 38 */ 39 public Calendar previous(Calendar current) { 40 return current == null ? null : changeCalendar(current, true); 41 } 42 43 /** 44 * get follow time base on dateModel 45 * <table> 46 * <tr><td>DATE_MODEL</td><td>RESULT</td></tr> 47 * <tr><td>DAY</td><td>Calendar.DATE += 1</td></tr> 48 * <tr><td>WEEK</td><td>Calendar.WEEK_OF_MONTH += 1</td></tr> 49 * <tr><td>MONTH</td><td>Calendar.MONTH += 1</td></tr> 50 * </table> 51 * @param current 52 * @return 53 */ 54 public Calendar follow(Calendar current) { 55 return current == null ? null : changeCalendar(current, false); 56 } 57 58 /** 59 * get first time base on dateModel 60 * <table> 61 * <tr><td>DATE_MODEL</td><td>RESULT</td></tr> 62 * <tr><td>DAY</td><td>current Date but 00:00:0000</td></tr> 63 * <tr><td>WEEK</td><td>first DATE_OF_WEEK 00:00:0000</td></tr> 64 * <tr><td>MONTH</td><td>first DATE_OF_MONTH 00:00:0000</td></tr> 65 * </table> 66 * @return 67 */ 68 public long startMills(Calendar current) { 69 return current == null ? 0 : getMills(current, true); 70 } 71 72 /** 73 * get first time base on dateModel 74 * <table> 75 * <tr><td>DATE_MODEL</td><td>RESULT</td></tr> 76 * <tr><td>DAY</td><td>current Date but 23:59:0000</td></tr> 77 * <tr><td>WEEK</td><td>last DATE_OF_WEEK 23:59:0000</td></tr> 78 * <tr><td>MONTH</td><td>last DATE_OF_MONTH 23:59:0000</td></tr> 79 * </table> 80 * @return 81 */ 82 public long endMills(Calendar current) { 83 return current == null ? 0 : getMills(current, false); 84 } 85 86 /** 87 * general range axis base on dateModel 88 * @param time 89 * @return 90 */ 91 public abstract List<Date> getRangeAxisesTime(Calendar time); 92 93 /** 94 * format time to String base on dateModel 95 * @return 96 */ 97 public String formatTime(Date date) { 98 return date == null ? null : format(date); 99 } 100 101 /** 102 * format time to String base on dateModel. 103 * it will be shown at the bottom label in chart. 104 * @param time 105 * @return 106 */ 107 public String formatTimeOnBottomLabel(Calendar time) { 108 return time == null ? null : formatBottomLabel(time); 109 } 110 111 /** 112 * get MIN display count base on dateModel 113 * <table> 114 * <tr><td>DATE_MODEL</td><td>Display min count</td></tr> 115 * <tr><td>DAY</td><td>3</td></tr> 116 * <tr><td>WEEK</td><td>2</td></tr> 117 * <tr><td>MONTH</td><td>1</td></tr> 118 * </table> 119 * @return 120 */ 121 public int displayViewMinCount() { 122 return 0; 123 } 124 125 /** 126 * get MAX display count base on dateModel 127 * @return max is 5 128 */ 129 public int displayViewMaxCount() { 130 return 5; 131 } 132 133 public boolean isNull() { 134 return false; 135 } 136 137 protected Calendar changeCalendar(Calendar current, boolean isPrevious) { 138 return null; 139 } 140 141 protected long getMills(Calendar current, boolean isStart) { 142 return 0; 143 } 144 145 protected String format(Date date) { 146 return null; 147 } 148 149 protected String formatBottomLabel(final Calendar time) { 150 return null; 151 } 152 153 private static class DM_UNKNOWN extends DateModel { 154 155 public DM_UNKNOWN(int code) { 156 super(code); 157 } 158 159 @Override 160 public boolean isNull() { 161 return true; 162 } 163 164 @Override 165 public List<Date> getRangeAxisesTime(Calendar time) { 166 return null; 167 } 168 169 } 170 171 private static class DM_DAY extends DateModel { 172 173 public DM_DAY(int code) { 174 super(code); 175 } 176 177 @Override 178 protected Calendar changeCalendar(Calendar current, 179 boolean isPrevious) { 180 Calendar calendar = (Calendar)current.clone(); 181 calendar.add(Calendar.DATE, isPrevious ? -1 : 1); 182 return calendar; 183 } 184 185 @Override 186 protected long getMills(Calendar current, boolean isStart) { 187 return isStart ? DateHelper.getStartMillsByDay(current) : 188 DateHelper.getEndMillsByDay(current); 189 } 190 191 @Override 192 public List<Date> getRangeAxisesTime(Calendar time) { 193 List<Date> dates = new LinkedList<Date>(); 194 Calendar c = (Calendar) time.clone(); 195 final int min = c.getActualMinimum(Calendar.HOUR_OF_DAY); 196 final int max = c.getActualMaximum(Calendar.HOUR_OF_DAY) / 6; 197 for (int i = min; i <= max; ++i) { 198 c.set(Calendar.HOUR_OF_DAY, i * 6); 199 CAdapter.formatTime(c, this); 200 dates.add(c.getTime()); 201 } 202 return dates; 203 } 204 205 @Override 206 protected String format(Date date) { 207 return (String) DateFormat.format(DateAxis.FORMAT_HOURMINUTE, date); 208 } 209 210 @Override 211 protected String formatBottomLabel(Calendar time) { 212 return (String) DateFormat.format("MM-dd", time); 213 } 214 215 @Override 216 public int displayViewMinCount() { 217 return 3; 218 } 219 220 } 221 222 private static class DM_WEEK extends DateModel { 223 public DM_WEEK(int code) { 224 super(code); 225 } 226 227 @Override 228 protected Calendar changeCalendar(Calendar current, 229 boolean isPrevious) { 230 Calendar calendar = (Calendar)current.clone(); 231 calendar.add(Calendar.WEEK_OF_MONTH, isPrevious ? -1 : 1); 232 return calendar; 233 } 234 235 @Override 236 protected long getMills(Calendar current, boolean isStart) { 237 return isStart ? DateHelper.getStartMillsByWeek(current) : 238 DateHelper.getEndMillsByWeek(current); 239 } 240 241 @Override 242 public List<Date> getRangeAxisesTime(Calendar time) { 243 List<Date> dates = new LinkedList<Date>(); 244 Calendar c = (Calendar) time.clone(); 245 final int min = c.getActualMinimum(Calendar.DAY_OF_WEEK); 246 final int max = c.getActualMaximum(Calendar.DAY_OF_WEEK); 247 for (int i = min; i <= max; ++i) { 248 c.set(Calendar.DAY_OF_WEEK, i); 249 CAdapter.formatTime(c, this); 250 dates.add(c.getTime()); 251 } 252 return dates; 253 } 254 255 @Override 256 protected String format(Date date) { 257 return (String) DateFormat.format(DateAxis.FORMAT_WEEK, date); 258 } 259 260 @Override 261 protected String formatBottomLabel(Calendar time) { 262 return (String) DateFormat.format("MM-dd", time); 263 } 264 265 @Override 266 public int displayViewMinCount() { 267 return 2; 268 } 269 } 270 271 private static class DM_MONTH extends DateModel { 272 public DM_MONTH(int code) { 273 super(code); 274 } 275 276 @Override 277 protected Calendar changeCalendar(Calendar current, 278 boolean isPrevious) { 279 Calendar calendar = (Calendar)current.clone(); 280 calendar.add(Calendar.MONTH, isPrevious ? -1 : 1); 281 return calendar; 282 } 283 284 @Override 285 protected long getMills(Calendar current, boolean isStart) { 286 return isStart ? DateHelper.getStartMillsByMonth(current) : 287 DateHelper.getEndMillsByMonth(current); 288 } 289 290 @Override 291 public List<Date> getRangeAxisesTime(Calendar time) { 292 List<Date> dates = new LinkedList<Date>(); 293 Calendar c = (Calendar) time.clone(); 294 final int min = c.getActualMinimum(Calendar.DAY_OF_MONTH); 295 final int max = c.getActualMaximum(Calendar.DAY_OF_MONTH); 296 for (int i = min; i <= max; ++i) { 297 c.set(Calendar.DAY_OF_MONTH, i); 298 CAdapter.formatTime(c, this); 299 dates.add(c.getTime()); 300 } 301 return dates; 302 } 303 304 @Override 305 protected String format(Date date) { 306 return (String) DateFormat.format(DateAxis.FORMAT_MONTH, date); 307 } 308 309 @Override 310 protected String formatBottomLabel(Calendar time) { 311 return (String) DateFormat.format("yyyy-MM", time); 312 } 313 314 @Override 315 public int displayViewMinCount() { 316 return 1; 317 } 318 } 319 }
虽然代码增长了好几十倍。但是通过继承,将与类型码相关的逻辑也封装在其中。
尤其是在调用时。不再需要判断类型。不再需要大段的switch语句。紧紧一行调用就能搞定。
同时还可以将NULL 融合进去。
谁用谁知道。用了都说好啊!

浙公网安备 33010602011771号