1.概念
每次只会创建同一个实例
2.实现步骤
- 构造函数私有化
- 对外暴露公共创建对象方式
3.常见单例模式
(1) 饿汉式
public class User{
private User(){
}
private static User instance = new User();
public static User getInstance(){
return instance;
}
}
(2) 懒汉式
public class User1 {
private User1(){
}
private static User1 instance = null;
public static User1 getInstance(){
if(null==instance){
synchronized (User1.class){
if(null==instance){
instance = new User1();
}
}
}
return instance;
}
}
(3) 内部类方式
public class User2 {
private User2(){}
private static class Holder{
private static User2 user2 = new User2();
}
public static User2 getInstance(){
return Holder.user2;
}
}
(4) 枚举方式
public class User3 {
private User3(){}
enum User3Enum{
INSTANCE;
private User3 user3;
User3Enum(){
user3 = new User3();
}
public User3 getInstance(){
return user3;
}
}
public static User3 getInstance(){
return User3Enum.INSTANCE.getInstance();
}
}
(5)测试
public class MainTest {
public static void main(String[] args){
User instance = User.getInstance();
User instance1 = User.getInstance();
System.out.println(instance==instance1);
User1 instance2 = User1.getInstance();
User1 instance3 = User1.getInstance();
System.out.println(instance2==instance3);
User2 instance4 = User2.getInstance();
User2 instance5 = User2.getInstance();
System.out.println(instance4==instance5);
}
}
-------------------------------------------------------------------------
// 结果:
true
true
true
4.存在问题
(1) 反射创建多个实例
Class<User> aClass = (Class<User>) Class.forName("com.xiaofengczy.design.create.singlefactory.User");
Constructor<User> declaredConstructor = aClass.getDeclaredConstructor(null);
declaredConstructor.setAccessible(true);
User user = declaredConstructor.newInstance();
User user1 = declaredConstructor.newInstance();
System.out.println(user==user1);
--------------------------------------------------------------------------
//结果:
false
--------------------------------------------------------------------------
//解决方式,在对象构造方法中进行处理
private User(){
if(instance!=null){
throw new RuntimeException();
}
}
(2) 序列化后创建多个实例
FileOutputStream fos = new FileOutputStream("/home/milk/Desktop/1.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(instance);
oos.close();
fos.close();
ObjectInputStream ois = new ObjectInputStream(
new FileInputStream("/home/milk/Desktop/1.txt"));
User u = (User) ois.readObject();
System.out.println(instance==instance1);
System.out.println(instance==u);
-------------------------------------------------------------------------
//输出结果
false
-------------------------------------------------------------------------
// 解决办法,要实例化对象中新增如下方法
private Object readResolve(){
return instance;
}