设计模式(三)Singleton Pattern单例设计模式

时间:2024-06-05 17:07:26

1.饿汉式

public class SingletonDemo {
private static SingletonDemo s=new SingletonDemo();
private SingletonDemo() {}
public static SingletonDemo getInstance() {
return s;
}
}
public class Test {
public static void main(String[] args) {
SingletonDemo s=SingletonDemo.getInstance();
}
}

步骤:    1.new出静态对象

    2.构造方法私有化

    3.写一个方法返回静态对象

说明:   1.由于加载类时天然的是线程安全

    2.方法没有同步,调用效率高

    3.立即加载,没有延时加载的优势

2.懒汉式(延时加载)

public class SingletonDemo {
private static SingletonDemo s;
private SingletonDemo() {}
public static synchronized SingletonDemo getInstance() {
if(s==null) s=new SingletonDemo();
return s;
}
}
public class Test {
public static void main(String[] args) {
SingletonDemo s=SingletonDemo.getInstance();
}
}

优势:   1.修改点同步,在线程高并发时,能够保证安全性

    2.延时new出类,能够做到用的时候去new它

3.双重检测锁实现

由于java编译器优化的原因和JVM底层内部模型的原因,偶尔会出一点问题,不建议使用

这个模式将同步内容下方到if内部,提高了执行效率,不必每次获取对象时都进行同步,至于一次才同步

public class SingletonDemo {
private static SingletonDemo instance;
private SingletonDemo() {}
public static SingletonDemo getInstance() {
if(instance==null) {
SiSingletonDemo sc;
synchronized (SingletonDemo.class) {
sc=instance;
}
if(sc==null) {
synchronized (SingletonDemo.class) {
if(sc==null) {
sc=new SingletonDemo();
}
}
instance=sc;
}
}
return instance;
}
}

4.静态内部类(懒加载)

public class SingletonDemo {
private static class SingletonClassInstance{
private static final SingletonDemo instance=new SingletonDemo();
}
private SingletonDemo() {}
public static SingletonDemo getInstance() {
return SingletonDemo.getInstance();
}
}

5.枚举单例模式

public enum SingletonDemo {
INSTANCE; //枚举本来就是单例对象
//避免了反序列和反射的调用
//缺点,没有延时调用
public void singletonOperation() { }
}

6.统一建模语言UML(unified modeling language)

可以拖动类做uml图

设计模式(三)Singleton Pattern单例设计模式

利用反射破解单例设计模式(不包含枚举单例,因为枚举型单例是利用JVM底层实现的单例设计模式)

public class TestSingleObject {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
SingleObject s1=SingleObject.getInstance();
SingleObject s2=SingleObject.getInstance(); Class<SingleObject> clazz=(Class<SingleObject>) Class.forName("com.littlepage.singletonPattern.SingleObject");
Constructor<SingleObject> c=clazz.getDeclaredConstructor(null);
c.setAccessible(true);//跳过检测
SingleObject s3=c.newInstance();
SingleObject s4=c.newInstance();
System.out.println(s1);
System.out.println(s2);
System.out.println(s3);
System.out.println(s4);
}
}

解决方法,在空参构造中加入

if(SingletonObject!=null){

throw new runtimeExpection();

}

进行调用时抛出异常就行

//举例
public class SingleObject {
public static class SingleObjectInstance{
public static final SingleObject instance=new SingleObject();
}
private SingleObject(){
if(SingleObjectInstance.instance!=null){
try {
throw new Exception("运行时异常"); } catch (Exception e) {
e.printStackTrace();
System.exit();
}
}
}
public static SingleObject getInstance(){
return SingleObjectInstance.instance;
}
}

利用序列化反序列化进行破解

public class TestSingleObject {
public static void main(String[] args) throws IOException, ClassNotFoundException {
SingleObject s1=SingleObject.getInstance();
System.out.println(s1);
FileOutputStream fops=new FileOutputStream("d:/a.txt");
ObjectOutputStream oops=new ObjectOutputStream(fops);
oops.writeObject(s1);
oops.close(); ObjectInputStream ois =new ObjectInputStream(new FileInputStream("d:/a.txt"));
SingleObject s2=(SingleObject) ois.readObject();
System.out.println(s2);
ois.close(); }
}

解决办法:

private Object resdResolve() throws ObjectStreamException{
return SingleObjectInstance.instance;
}

添加该代码,可以使读取Object时直接返回已经存在的实例