Java枚举,酷! (原文发表于2006-04-25 下午01:13:48)

当我头一次看到Java 5中的新登场的枚举类型(译注:enum)时,我还是持怀疑态度的。这些枚举类型允许你定义成员和方法(译注:variables and methods)甚至是抽象方法!你能用它来做什么呢?嗯,我现在已经找到了这个问题的答案。(至少是部分的)

在评阅和改进外面的一些源码的过程中,我有机会找到了一组用来代表月份的私有静态常量(译注:static final constants),并把他们转换成了Month枚举。起初,这个Month枚举仅仅是个简单的枚举,但随着我进一步改进这些源码时,我发现了越来越多的操作月份常量的方法,或者说,是一些与月份常量紧密关联的方法。每次我发现一个就把它放到Month枚举之中。结果如下:

import java.text.DateFormatSymbols;
public enum Month {
  JANUARY(1), FEBRUARY(2), MARCH(3),
  APRIL(4),   MAY(5),      JUNE(6),
  JULY(7),    AUGUST(8),   SEPTEMBER(9),
  OCTOBER(10),NOVEMBER(11),DECEMBER(12);

  private static DateFormatSymbols dateFormatSymbols = new DateFormatSymbols();
  private static final int[] LAST_DAY_OF_MONTH =
    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

  public int index;

  Month(int index) {
    this.index = index;
  }

  public static Month make(int monthIndex) {
    for (Month m : Month.values()) {
      if (m.index == monthIndex)
        return m;
    }
    throw new IllegalArgumentException("Invalid month index " + monthIndex);
  }

  public int lastDay() {
    return LAST_DAY_OF_MONTH[index];
  }

  public int quarter() {
    return 1 + (index - 1) / 3;
  }

  public String toString() {
    return dateFormatSymbols.getMonths()[index - 1];
  }

  public String toShortString() {
    return dateFormatSymbols.getShortMonths()[index - 1];
  }

  public static Month parse(String s) {
    s = s.trim();
    for (Month m : Month.values())
      if (m.matches(s))
        return m;

    try {
      return make(Integer.parseInt(s));
    }
    catch (NumberFormatException e) {}
    throw new IllegalArgumentException("Invalid month " + s);
  }

  private boolean matches(String s) {
    return s.equalsIgnoreCase(toString()) ||
           s.equalsIgnoreCase(toShortString());
  }
}

我发现这很值得注意,也很有用。现在我就可像这样来描述事情:

Month m = Month.parse(inputString);

或是

Month m...;

int lastDay = m.lastDay();

Java 5的枚举并不定义常量,它们在一个类之中定义了单例(译注1)对象。有一个类叫Month,还有另外一个代表JANUARY的类从Month派生。这个JANUARY类有唯一的一个单例叫JANUARY。这个JANUARY类的单例就是JANUARY的枚举对象。

事实上,枚举是一种创建单例类的方法。每个枚举对象决不会拥有超过一个的实例,而且这个实例在枚举被使用之前(可能在加载过程中)就被构建了。而现在枚举对象就是一些类,它们充满着类天生的各种技能。下次你再想要单例的时候考虑一下这个:

enum Database {

INSTANCE;

public void open() {...}

...

}

你可以像这样来使用它:

Database.INSTANCE.open(...);

  

译注:

1,单例,原文singleton,一种常用的设计模式,详细介绍可参见uncle bob的著作《敏捷软件开发:原则、模式与实践》一书。

 

 (原文链接网址:http://www.butunclebob.com/ArticleS.UncleBob.JavaEnums; Robert C. Martin的英文blog网址: http://www.butunclebob.com/ArticleS.UncleBob 

作者简介:Robert C. MartinObject Mentor公司总裁,面向对象设计、模式、UML、敏捷方法学和极限编程领域内的资深顾问。他不仅是Jolt获奖图书《敏捷软件开发:原则、模式与实践》(中文版)(《敏捷软件开发》(英文影印版))的作者,还是畅销书Designing Object-Oriented C++ Applications Using the Booch Method的作者。MartinPattern Languages of Program Design 3More C++ Gems的主编,并与James Newkirk合著了XP in Practice。他是国际程序员大会上著名的发言人,并在C++ Report杂志担任过4年的编辑。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章