单例模式

今天图图给大家细说一番单例模式。
设计模式是一种思想,最早用于建筑,后来也用到我们软件开发上来,是牛人总结的一些常见的架构思想,按照六中原则设计出来的23中设计模式
单例模式:是23中设计模式最简单的设计模式,也是很常见的设计模式,  java中一般体现在框架的整体架构,面向接口编程,用这种思想完成某个领域的解决方案。
当然实现单例功能后,保证线程安全,并发效率快,消耗资源率少的原则才是最perfect。
详情请往下看。

单例模式自身的初衷在于应用程序一启动,单例资源一次性永久驻留内存的思想,



package org.huey.pattern.singleton1;

/**
 * 懒汉式单例模式
 * @author huey
 *
 */
public class HungryStyle {


     //public Integer number;
     //private Integer number;
     /**
      * 类属性,天然线程安全
      */
     private static HungryStyle hungryStyle = new HungryStyle();

     private HungryStyle() {
     }

     public static HungryStyle getInstance() {
          return hungryStyle;
     }
}

饿汉式
缺点:上来就创建对象,立刻加载,如果我不用getInstance方法的话,那么就浪费了创建所耗的资源。
优点:类属性线程安全,方法不用同步锁也没有并发问题,调用效率高。




package org.huey.pattern.singleton1;

/**
 * 懒汉式加载
 * @author huey
 *
 */
public class LazyStyle {

     private static LazyStyle lazyStyle;

     private LazyStyle() {
     }

     public synchronized static LazyStyle getInstance() {

          if (lazyStyle == null) {
               //---------------此处如果有多个线程访问,一个线程挂机,当另一个线程进来时,lazyStyle依然为null
              //那么就都去new对象了,失去了初衷(只创建一次),故加上synchronized同步锁
              lazyStyle = new LazyStyle();
          }
          return lazyStyle;
     }
}


懒汉式
缺点:由于存在并发问题,需要加上同步锁解决线程安全问题,故调用效率低。
优点:使用的时候再创建,资源利用率高。




package org.huey.pattern.singleton1;

/**
 * 静态内部类的单例模式
 * @author huey
 *
 */
public class StaticInnerStyle {

     //静态内部类不会随这类加载而加载,当你调用getInstance方法才会加载该内部类,也就是懒加载
     private static class SingletionClass{
           //类属性,线程安全
           private static final StaticInnerStyle instance = new StaticInnerStyle();
     }
     //不用同步锁,调用效率高
     public static StaticInnerStyle getInstance(){
          return SingletionClass.instance;
     }

     private StaticInnerStyle(){}
}

静态内部类的单例:
优点:高效(不用同步锁) 线程安全(静态类属性) 懒加载(使用时我才创建)



package org.huey.pattern.singleton1;

/**
 * 枚举类型的单例模式
 * @author huey
 *
 */
public enum EnumStyle {

      //枚举天然是单例,jvm的底层实现,不过用枚举实现单例,要求只有这一个对象
     INSTANCE;
      //INSTANCE,SPRING;这样如果测试INSTANCE与SPRING不是通一个对象


     public void service(){
          System.out.println("业务操作....");
     }
}


借助jad工具进行反编译,代码如下


// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3)
// Source File Name:   EnumStyle.java
// 反编译
package org.huey.pattern.singleton1;

import java.io.PrintStream;

public final class EnumStyle extends Enum
{

     private EnumStyle(String s, int i)
    {
        super(s, i);
    }

     public void service()
    {
        System.out.println("\u4E1A\u52A1\u64CD\u4F5C....");
    }

    public static EnumStyle[] values()
    {
        EnumStyle aenumstyle[];
        int i;
        EnumStyle aenumstyle1[];
         System.arraycopy(aenumstyle = ENUM$VALUES, 0, aenumstyle1 = new EnumStyle[i = aenumstyle.length], 0, i);
        return aenumstyle1;
    }

    public static EnumStyle valueOf(String s)
    {
        return (EnumStyle)Enum.valueOf(org/huey/pattern/singleton1/EnumStyle, s);
    }

     public static final EnumStyle INSTANCE;
    private static final EnumStyle ENUM$VALUES[];

     static
    {
        INSTANCE = new EnumStyle("INSTANCE", 0);
        ENUM$VALUES = (new EnumStyle[] {
            INSTANCE,
        });
    }
}


反编译后,会学到很多知识,数组的最佳复制操作,字符串转为Unicode的码,还有一个是目标匿名内部类的数组形式,头一次发现,学到了不少东西,很开心。
其枚举类型的单例 优点 线程安全,高效, 缺点是 没有延迟加载(可通过反编译代码看出),还有就是只有这种方式,可以避免反射(不考虑特殊处理)和反序列化漏洞,其他的形式的单例模式做不到这一点,换句话说反射和反编译能破解其他形式的单例模式


注:
 
一般单例用途就是用在他的功能,只加载一次就够。比如springmvc的前端控制器,spring的ioc,加载配置文件的配置器类,创建框架内部对象的工厂类,处理日志类等。
还有一种好像叫双重内部锁,由于该方式双同步可能次序不易可能存在问题,就不说了,主要是没研究过。。。。



附加Enum抽象类jdk源码
/*
 * @param <E> The enum type subclass
 * @author  Josh Bloch
 * @author  Neal Gafter
 * @see     Class#getEnumConstants()
 * @see     java.util.EnumSet
 * @see     java.util.EnumMap
 * @since   1.5
 */
public abstract class Enum<E extends Enum<E>>
        implements Comparable<E>, Serializable {

    private final String name;


    public final String name() {
        return name;
    }


    private final int ordinal;


    public final int ordinal() {
        return ordinal;
    }


    protected Enum(String name, int ordinal) {
        this.name = name;
        this.ordinal = ordinal;
    }


    public String toString() {
        return name;
    }

    public final boolean equals(Object other) {
        return this==other;
    }


    public final int hashCode() {
        return super.hashCode();
    }


    protected final Object clone() throws CloneNotSupportedException {
        throw new CloneNotSupportedException();
    }

    public final int compareTo(E o) {
        Enum other = (Enum)o;
        Enum self = this;
        if (self.getClass() != other.getClass() && // optimization
            self.getDeclaringClass() != other.getDeclaringClass())
            throw new ClassCastException();
        return self.ordinal - other.ordinal;
    }


    public final Class<E> getDeclaringClass() {
        Class clazz = getClass();
        Class zuper = clazz.getSuperclass();
        return (zuper == Enum.class) ? clazz : zuper;
    }


    public static <T extends Enum<T>> T valueOf(Class<T> enumType,
                                                String name) {
        T result = enumType.enumConstantDirectory().get(name);
        if (result != null)
            return result;
        if (name == null)
            throw new NullPointerException("Name is null");
        throw new IllegalArgumentException(
            "No enum constant " + enumType.getCanonicalName() + "." + name);
    }


    private void readObject(ObjectInputStream in) throws IOException,
        ClassNotFoundException {
        throw new InvalidObjectException("can't deserialize enum");
    }

    private void readObjectNoData() throws ObjectStreamException {
        throw new InvalidObjectException("can't deserialize enum");
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值