单例模式是常见的设计模式,也是最被滥用的设计模式.
单例模式分为两种:
懒汉式:第一次getInstance的时候加载;
饿汉式:申明的时候加载
懒汉式为大多数人喜欢,因为他复杂.而且据说延迟加载据说能提示性能.首先懒汉式是线程不安全的,在多线程的环境下要加锁.
以上两个是可行的懒汉式单例,不过我觉得背离了面向对象的初衷,特别是第二种,面向对象里的class都是有具体意义的,这里的class没有,只是为了实现单例.
饿汉式是简单安全的,这也是高级编程语言的目标.因此在我看来,设计模式的单例模式在java 中应该以单例模式的形式实现.
饿汉式:
因此,推荐使用饿汉式,当然懒汉式也要了解,可能有点面试官比较热衷.
其次,讨论一下,单例模式与静态类的区别,以及如何选择:
这里抛开懒汉式,因为它很不面向对象.
其实只有一点区别:单例模式能继承其他的类和接口(其余的优点均是yy),因此,在调用的时候,可以比较符合依赖抽象的原则(接口调用接口的方式写代码).
注意:继承了其他类的话,父类不是单例.单例和静态类均不能被继承.单例和静态类均可以保存状态
单例模式的构成:
私有的构造器
私有的对象属性
公共的get方法
单例模式分为两种:
懒汉式:第一次getInstance的时候加载;
饿汉式:申明的时候加载
懒汉式为大多数人喜欢,因为他复杂.而且据说延迟加载据说能提示性能.首先懒汉式是线程不安全的,在多线程的环境下要加锁.
常用的方法是双重检查+volatile 关键字:
public class Instance {
private static volatile Instance instance;//volatile据说要这个关键字修饰,这个我没测试出反例
private Instance(){}
public static Instance getInstance(){
//两次检查是否为null
if(instance==null){
synchronized(Instance.class){
if(instance==null){
instance=new Instance();
}
}
}
return instance;
}
}
或者用静态内部类实现:
public class Instance {
private Instance(){
System.out.println("调用Instance构造器");
}
public static Instance getInstance(){
System.out.println("调用getInstance");
return InnerClass.getSingle();
}
//关键点在于静态内部类只会在使用时加载,并且由jvm保证线程安全
private static class InnerClass{
private static Instance instance=new Instance();
public static Instance getSingle(){
return instance;
}
}
}
调试:
public static void main(String[] args) {
Instance instance=Instance.getInstance();
}
结果:
调用getInstance
调用Instance构造器
以上两个是可行的懒汉式单例,不过我觉得背离了面向对象的初衷,特别是第二种,面向对象里的class都是有具体意义的,这里的class没有,只是为了实现单例.
饿汉式是简单安全的,这也是高级编程语言的目标.因此在我看来,设计模式的单例模式在java 中应该以单例模式的形式实现.
饿汉式:
class Single{
private static Single single=new Single();
private Single(){
}
public static Single getSingle(){
return single;
}
}
因此,推荐使用饿汉式,当然懒汉式也要了解,可能有点面试官比较热衷.
其次,讨论一下,单例模式与静态类的区别,以及如何选择:
这里抛开懒汉式,因为它很不面向对象.
其实只有一点区别:单例模式能继承其他的类和接口(其余的优点均是yy),因此,在调用的时候,可以比较符合依赖抽象的原则(接口调用接口的方式写代码).
注意:继承了其他类的话,父类不是单例.单例和静态类均不能被继承.单例和静态类均可以保存状态