类型码从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 融合进去。

谁用谁知道。用了都说好啊!

 

posted @ 2013-03-15 18:31  wFeng  阅读(310)  评论(0)    收藏  举报