Effective Java Item3:使用私有构造方法或者枚举类型实现单例

Item3 Enforce the singleton property with a private constructor or an enum type

使用私有构造方法或者枚举类型实现单例。

 

单例(Singleton)是指只实例化一次的类。

单例表示本质上唯一的系统组件,例如文件系统或者窗口管理器。

package com.googlecode.javatips4u.effectivejava.singleton;

 

public class StaticFinalFieldSingleton {

      public static final StaticFinalFieldSingleton INSTANCE = new StaticFinalFieldSingleton();

 

      private StaticFinalFieldSingleton() {

      }

}

当类StaticFinalFieldSingleton类被实例化时,有且仅有一个StaticFinalFieldSingleton实例存在。

(除非客户端通过类反射机制调用该私有的构造方法,否则外部无法改变单例)

package com.googlecode.javatips4u.effectivejava.singleton;

 

public class StaticFactoryMethodSingleton {

 

      private static final StaticFactoryMethodSingleton INSTANCE = new StaticFactoryMethodSingleton();

 

      private StaticFactoryMethodSingleton() {

      }

 

      public static StaticFactoryMethodSingleton getInstance() {

            return INSTANCE;

      }

}

public static final成员的优点在于客户端很容易分辨是单例。static(整个类公用的)final(不能改变的)确保实例是相同对象的引用。

public static method的优点在于增加了灵活性,可以修改方法内部而不引起客户端API的改变,例如每个线程一个单例。另外一个有点在于涉及到泛型的时候(Item27)

Item27

当对单例类进行Serializable处理时,仅仅实现Serializable接口还是不够的,确切的说,如果只是实现Serializable接口,那么被readObject读取的实例并不是writeObject时存储的类。

需要将所有的实例成员设置为transient(why???),然后实现readResolve()方法:

ObjectInputStream.readObject() -> ObjectInputStream.readObject0(boolean) -> ... -> Method.invoke() -> ... SerializableSingleton.readResolve()

例如在下面的例子中,如果不实现readResolve()方法,那么writereadobject是不同的实例。

package com.googlecode.javatips4u.effectivejava.singleton;

 

import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import java.io.Serializable;

 

public class SerializableSingleton implements Serializable {

 

      private String mDesc = "I am transient";

 

      private static final long serialVersionUID = 1L;

      private static final SerializableSingleton INSTANCE = new SerializableSingleton();

 

      private SerializableSingleton() {

      }

 

      public static SerializableSingleton getInstance() {

            return INSTANCE;

      }

 

      public String getDesc() {

            return mDesc;

      }

 

      public void setDesc(String desc) {

            this.mDesc = desc;

      }

 

      // readResolve method to preserve singleton property

      public Object readResolve() {

            return INSTANCE;

      }

 

      public static void main(String[] args) {

            File file = new File("singleton");

            ObjectOutputStream oos = null;

            ObjectInputStream ois = null;

            try {

                  oos = new ObjectOutputStream(new FileOutputStream(file));

                  SerializableSingleton instance = SerializableSingleton

                              .getInstance();

                  instance.setDesc("I changed you!");

                  System.out.println(instance);

                  oos.writeObject(instance);

                  oos.close();

                  ois = new ObjectInputStream(new FileInputStream(file));

                  SerializableSingleton instance2 = (SerializableSingleton) ois

                              .readObject();

                  System.out.println(instance2);

                  System.out.println(instance2.getDesc());

            } catch (FileNotFoundException e) {

                  e.printStackTrace();

            } catch (IOException e) {

                  e.printStackTrace();

            } catch (ClassNotFoundException e) {

                  e.printStackTrace();

            } finally {

                  if (oos != null) {

                        try {

                              oos.close();

                        } catch (IOException e) {

                              e.printStackTrace();

                        }

                  }

                  if (ois != null) {

                        try {

                              ois.close();

                        } catch (IOException e) {

                              e.printStackTrace();

                        }

                  }

            }

      }

}

Java1.5中,还有另外一种方法来实现单例,那就是枚举类型:a single-element enum type is the best way to implement a singleton.单元素的枚举类型是实现单例的最好方式。

package com.googlecode.javatips4u.effectivejava.singleton;

 

import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import java.io.Serializable;

 

public enum EnumSingleton implements Serializable {

 

      INSTANCE;

      private String book = null;

 

      public String getBook() {

            return book;

      }

 

      public void setBook(String book) {

            this.book = book;

      }

 

      public void doSomething() {

      };

}

 

class EnumSingletonSerialization {

      public static void main(String[] args) {

            File file = new File("singleton");

            ObjectOutputStream oos = null;

            ObjectInputStream ois = null;

            try {

                  oos = new ObjectOutputStream(new FileOutputStream(file));

                  EnumSingleton singleton = EnumSingleton.INSTANCE;

                  singleton.setBook("HelloWorld");

                  oos.writeObject(EnumSingleton.INSTANCE);

                  System.out.println(EnumSingleton.INSTANCE);

                  oos.close();

                  ois = new ObjectInputStream(new FileInputStream(file));

                  EnumSingleton singleton2 = (EnumSingleton) ois.readObject();

                  System.out.println(singleton2.getBook());

                  System.out.println(singleton == singleton2);

            } catch (FileNotFoundException e) {

                  e.printStackTrace();

            } catch (IOException e) {

                  e.printStackTrace();

            } catch (ClassNotFoundException e) {

                  e.printStackTrace();

            } finally {

                  if (oos != null) {

                        try {

                              oos.close();

                        } catch (IOException e) {

                              e.printStackTrace();

                        }

                  }

                  if (ois != null) {

                        try {

                              ois.close();

                        } catch (IOException e) {

                              e.printStackTrace();

                        }

                  }

            }

      }

}

你可能感兴趣的:(java,String,File,null,Class,Constructor)