前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >图图细谈设计模式——单例模式

图图细谈设计模式——单例模式

作者头像
一头小山猪
发布2020-04-10 10:47:13
3210
发布2020-04-10 10:47:13
举报
文章被收录于专栏:微光点亮星辰微光点亮星辰

图图在为毕业设计的事忙来忙去,有时间就回来讲故事。

图图在为面试做准备,今天图图给大家细说一番单例模式。其实最简单的是工厂模式而不是单例(工厂后续会说)

设计模式是一种思想,最早用于建筑,后来也用到我们软件开发上来,是牛人总结的一些常见的架构思想,按照六中原则设计出来的23中设计模式

单例模式:是23中设计模式稍简单的设计模式,也是很常见的设计模式, java中一般体现在框架的整体架构,面向接口编程,用这种思想完成某个领域的解决方案。

当然实现单例功能后,保证线程安全,并发效率快,消耗资源率少的原则才是最perfect。

详情请往下看。

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


代码语言:javascript
复制
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方法的话,那么就浪费了创建所耗的资源。

优点:类属性线程安全,方法不用同步锁也没有并发问题,调用效率高。


代码语言:javascript
复制
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;
     }
}

懒汉式

缺点:由于存在并发问题,需要加上同步锁解决线程安全问题,故调用效率低。

优点:使用的时候再创建,资源利用率高。


代码语言:javascript
复制
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(){}
}

静态内部类的单例:

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


代码语言:javascript
复制
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源码

代码语言:javascript
复制
/*
 * @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");
    }
}
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2016-11-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 微光点亮星辰 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档