目录
单例设计模式:在一些系统中,有的类被规定只能提供一个实例化对象,这时就可以使用单例设计模式。这时就可以将构造方法私有化进行封装使得在类的外部无法实例化新的对象,而在类的内部进行实例化对象的创建,并且提供共有的getInstance方法返回固定的实例化对象。类的这种设计模式就称为单例设计模式。单例设计模式分为饿汉式和懒汉式。
饿汉式单例设计模式,在类中定义成员属性时直接进行了对象的实例化:
- public class SingleObject {
- private final String name = "阿里云";
- private static final SingleObject SINGLE = new SingleObject();//只产生一份实例化对象
- private SingleObject() {} //构造方法私有化,再类的外部无法new新对象
-
- /**
- * 获取本地实例化对象,使用static修饰不收实例化对象的限制
- * @return SINGLE内部实例化对象
- */
- public static SingleObject getInstance() {
- return SINGLE; //返回单一对象SINGLE
- }
- @Override
- public String toString() {
- return name;
- }
- }
- public class SingleObjectTestDrive {
- public static void main(String[] args) {
- SingleObject singleObject = SingleObject.getInstance();
- System.out.println(singleObject);
- }
- }
懒汉式单例设计模式,在第一次使用类的时候在进行对象的实例化:
- private static final SingleObject INSTANCE;
- ......
- public SingleObject getInstance() {
- if(INSTANCE == null) {
- INSTANCE = new SingleObject;
- }
- return INSTANCE;
- }
多例设计模式:类似于单例设计模式,在一个系统中,有的类可能需要固定个数的特定的实例化对象,如四季,只有春夏秋冬,这个时候就应当限制对象的实例化,而不是由用户随意的实例化对象。这是就可以使用多例设计模式在类的内部提供好实例化对象后进行类的封装,然后提供给用户固定的实例化对象。
多例设置模式的实例:
- public class Season {
- private String season;
- private String desc;
- public static final Season SPRING = new Season("春天","温暖");
- public static final Season SUMMER = new Season("夏天","炎热");
- public static final Season AUTUMN = new Season("秋天","凉爽");
- public static final Season WINTER = new Season("春天","寒冷");
- private Season(String season,String desc) {//构造方法私有化,在类的外部无法进行对象的实例化
- this.season = season;
- this.desc = desc;
- }
- @Override
- public String toString() {
- return "Season{" +
- "season='" + season + '\'' +
- ", desc='" + desc + '\'' +
- '}';
- }
- }
为了解决单例设计模式和多利设计模式的缺陷问题,自JDK1.5之后,Java提供了通过enum关键字定义的枚举结构,对多例设计模式进行简化。
使用enum关键字定义枚举类时的注意事项:
使用枚举实现多例设计模式中的类体:
- public enum Season {
- //枚举对象必须定义在枚举类的行首
- SPRING("春天","温暖"),//这里相当于将public static final Season season = new Season("春天","温暖")进行了简写
- SUMMER("夏天","炎热"),
- AUTUMN("秋天","凉爽"),
- WINTER("冬天","寒冷");
- private String season; //描述季节的属性
- private String desc; //描述季节的特征的属性
- //提供对应枚举类定义的构造方法
- private Season(String season,String desc) {
- this.season = season;
- this.desc = desc;
- }
- @Override //覆写父类中的toString方法
- public String toString() {
- return "Season{" +
- "season='" + season + '\'' +
- ", desc='" + desc + '\'' +
- '}';
- }
- }
- class TestsMain() {
- public static void main(String[] args) {
- Season spr = Season.SPRING;
- System.out.println(spr);//输出:Season{season='春天', desc='温暖'}
- System.out.println(Arrays.toStirng(Season.values()));//values方法返回所有的枚举对象,于一个Season[]数组中
- }
- }
对于通过enum关键字定义的枚举类默认继承自Enum类可以通过反编译进行证明:
对上述的Seaon枚举类进行反编译:
使用enum关键字定义的枚举类,是默认被final关键字修饰并且继承自Enum父类的,观察Enum父类,可以知道通过在enum关键字定义的枚举类中的枚举对象的名称存在于Enum父类的name属性中的:
并且在Enum父类中提供了很多操作枚举对象的方法:
- @Override //覆写父类中的toString方法,用于输出当前枚举对象的信息
- public String toString() {
- return "Season{" +
- "season='" + season + '\'' +
- ", desc='" + desc + '\'' +
- '}';
- }
- //创建了一个枚举类Season,四个枚举对象SPRING,SUMMER,AUTUMN,WINTER
- Season spring = Season.SPRING;
- System.out.println(spring.name());//调用当前枚举对象的name方法,输出SPRING
- //创建了一个枚举类Season,四个枚举对象SPRING,SUMMER,AUTUMN,WINTER
- for (Season temp : Season.values()) { //for each遍历Season类型的枚举对象
- System.out.println(temp.ordinal()); //输出每一个枚举对象的编号
- }
- //输出:0 1 2 3
values()
返回当前枚举类中的所有枚举对象组成的一个枚举类型的数组。
- //创建了一个枚举类Season,四个枚举对象SPRING,SUMMER,AUTUMN,WINTER
- System.out.println(Arrays.toString(Season.values()));
- //输出:[Season{season='春天', desc='温暖'}, Season{season='夏天', desc='炎热'}, Season{season='秋天', desc='凉爽'}, Season{season='冬天', desc='寒冷'}]
valueOf()
静态方法,将一个字符串转换为枚举对象,返回该枚举对象供后续使用。要求字符串必须为已有常量名,否则将抛出
- //创建了一个枚举类Season,四个枚举对象SPRING,SUMMER,AUTUMN,WINTER
- System.out.println(Season.valueOf("SUMMER").ordinal());
- //输出:1
compareTo()
观察Enum类可以发现该类实现了Comparable接口,所以可以进行枚举对象之间的比较,两个枚举之间比较的是两个枚举常量的位置号,返回调用该方法的枚举常量的位置号和进行比较的枚举常量的位置号的差值。
- //创建了一个枚举类Season,四个枚举对象SPRING,SUMMER,AUTUMN,WINTER
- System.out.println(Season.AUTUMN.compareTo(Season.SPRING));
- //输出:2