设计模式之创建者模式-单例模式

设计模式之创建者模式-单例模式

单例模式的演变与最终合适的创建单例模式的方法

1.饿汉式:见名知意,已经迫不及待了,在项目初始化的时候就要创建出来这个单实例,这种创建方式,线程安全,但是创建时机过早,哪怕我不用实例都要创建;

/**
 1. @author pozhang
 */
public class SingletonClass {

    private static SingletonClass singleton=new SingletonClass();
    
    public static SingletonClass getInstance(){
        return singleton;
    }
}

2.懒汉式:与饿汉式相反,懒得弄,我需要的时候再创建,不需要不创建,什么时候需要呢?这样吧,就在获取的时候是偷懒最长的时候,哈哈

2.1.对于新手可能的操作,这种存在线程安全问题 ,多线程无法保证单实例,那好,我们在方法上加上synchronized或者用synchronized静态代码块全部包裹住 ,这样可以吗?可以,但是效率低下(相对后面的方式来说 ,hiahia),该怎么样呢,请看2.2

/**
 * @author pozhang
 */
public class SingletonClass {

    private static SingletonClass singleton = null;

    public static SingletonClass getInstance() {
        if (singleton == null) {
            singleton = new SingletonClass();
        }
        return singleton;
    }
}

2.2 使用下面的代码只需要第一次实例化的时候保证线程安全就可以了,其他时候直接获取,不会产生线程安全问题,大家注意看,这里实例singleton==null判断了两次,这种锁外锁内两次判断的操作,被称为双重检查锁机制,这是因为什么,假设现在两个线程同时到达第一个判断为null,此时第一个线程进入代码块实例化成功,此时如果没有第二个判断,那么实例会再次实例化,对象确实还是只有一个实例,但是对象变了,也违反单实例的定义,所以静态代码块 也需要再次判空操作(这里volatile 的作用是 为了防止指令重排,写要优先于读执行,java1.5之前是没有这种操作的,java1.5之前这种创建依然不安全,一个线程可看到 另一个线程初始化一半的实例 )

/**
 * @author pozhang
 */
public class SingletonClass {

    private static volatile SingletonClass singleton=null;

    public static SingletonClass getInstance(){
        if (singleton==null){
            synchronized (SingletonClass.class){
                if (singleton==null){
                    singleton=new SingletonClass();
                }
            }
        }
        return singleton;
    }
}

3.静态持有者模式:通过静态内部类的方式实现单例模式是线程安全的,同时静态内部类不会在Singleton类加载时就加载,而是在调用getInstance()方法时才进行加载,达到了懒加载的效果。

/**
 * @author pozhang
 */
public class SingletonClass {

   private static class SingletonClassHolder{
       private static SingletonClass singleton=new SingletonClass();
   }
   
   public static SingletonClass getInstance(){
       return SingletonClassHolder.singleton;
   }
}

静态内部类看起来已经是最完美的方法了,其实不是,可能还存在反射攻击或者反序列化攻击,但是一般应该没人这么干:

Singleton singleton = Singleton.getInstance();
    Constructor<Singleton> constructor = Singleton.class.getDeclaredConstructor();
    constructor.setAccessible(true);
    Singleton newSingleton = constructor.newInstance();
    System.out.println(singleton == newSingleton);

运行结果,读者可自己试下,结果 为false,这样的话,这种方式也不是什么最好的操作 ;
4.最终方案:最佳的单例实现模式就是枚举模式。利用枚举的特性,让JVM来帮我们保证线程安全和单一实例的问题,而且写法超级简单:

/**
 * @author pozhang
 */
public enum SingletonClass {

    INSTANSE;

    public static SingletonClass getInstance() {
        return INSTANSE;
    }
}

至此,单例模式讨论到此结束

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
设计模式除了单例模式,还有很多其他常见的设计模式,例如: 1. 工厂模式(Factory Pattern):用于创建对象的模式,根据不同的条件返回不同的对象实例。 2. 观察者模式(Observer Pattern):定义了一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。 3. 建造者模式(Builder Pattern):将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。 4. 适配器模式(Adapter Pattern):将一个类的接口转换成客户希望的另一个接口,使得原本不兼容的类可以一起工作。 5. 策略模式(Strategy Pattern):定义了一系列的算法,并将每个算法封装起来,使它们可以互相替换,使得算法可以独立于使用它的客户而变化。 6. 装饰器模式(Decorator Pattern):动态地给一个对象添加一些额外的职责,就增加功能来说,装饰器模式比生成子类更为灵活。 7. 模板方法模式(Template Method Pattern):定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 8. 迭代器模式(Iterator Pattern):提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。 9. 外观模式(Facade Pattern):为子系统中的一组接口提供一个一致的界面,定义了一个高层接口,使得这个子系统更加容易使用。 10. 访问者模式(Visitor Pattern):表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值