单例模式
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。属于创建型模式,其提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
注意:
1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。
分类
1,饿汉式静态常量
2,饿汉式方法块
3,懒汉式静态常量
4,懒汉式同步代码块
代码实现
1,饿汉式静态常量(为了易于区分类名用了中文,不提倡)
public class A饿汉式静态常量 {
public static void main(String []args) {
Singleton1 instance= Singleton1.getInstance();
Singleton1 instance1= Singleton1.getInstance();
System.out.println(instance.hashCode());
System.out.println(instance1.hashCode());
}
}
//饿汉式(静态常量)
class Singleton1{
//构造器私有化,外部不能new
private Singleton1() {
System.out.println("饿汉式实现:Db连接成功");
System.out.println();
}
//本类内部创建对象实例
private final static Singleton1 instance= new Singleton1();
//提供一个共有的静态方法,返回实例对象
public static Singleton1 getInstance() {
return instance;
}
}
2,饿汉式方法块
/**
*
* @author 22247
*缺点:慢,线程不安全
*/
public class B饿汉式方法块 {
public static void main(String []args) {
Singleton2 instance= Singleton2.getInstance();
Singleton2 instance1= Singleton2.getInstance();
System.out.println(instance.hashCode());
System.out.println(instance1.hashCode());
}
}
//饿汉式
class Singleton2{
//构造器私有化,外部不能new
private Singleton2() {
System.out.println("饿汉式实现:Db连接成功");
System.out.println();}
//本类内部创建对象实例
private static Singleton2 instance;
static {
instance= new Singleton2();
}
//提供一个共有的静态方法,返回实例对象
public static Singleton2 getInstance() {
return instance;
}
}
3,懒汉式静态常量
/***
*
* @author 22247
*缺点:慢,线程不安全,实际开发不用
*/
public class C懒汉式静态常量 {
public static void main(String []args) {
Singleton21 instance= Singleton21.getInstance();
Singleton21 instance1= Singleton21.getInstance();
System.out.println(instance.hashCode());
System.out.println(instance1.hashCode());
}
}
//懒汉式(静态变量)
class Singleton21{
//构造器私有化,外部不能new
private Singleton21() {
System.out.println("懒汉式实现:Db连接成功");
System.out.println();}
//本类内部创建对象实例
private static Singleton21 instance= null;
//提供一个共有的静态方法,返回实例对象
//public static Singleton21 getInstance() {
//加同步锁
public static synchronized Singleton21 getInstance() {
if(instance==null)
instance=new Singleton21();
return instance;
}
}
4,懒汉式同步代码块
/**
*
* @author 22247
*不能用,线程不安全
*/
public class D懒汉模式同步代码块 {
public static void main(String []args) {
Singleton22 instance= Singleton22.getInstance();
Singleton22 instance1= Singleton22.getInstance();
System.out.println(instance.hashCode());
System.out.println(instance1.hashCode());
}
}
//懒汉式(同步代码块)
class Singleton22{
//构造器私有化,外部不能new
private Singleton22() {
System.out.println("懒汉式同步代码块实现:Db连接成功");
System.out.println(); }
//本类内部创建对象实例
private static Singleton22 instance= null;
//提供一个共有的静态方法,返回实例对象
public static Singleton22 getInstance() {
if(instance==null) {
synchronized (Singleton22.class) {
instance=new Singleton22();
}
}
return instance;
}
}
区别
1,静态常量和代码块在代码写法上区别不大,前者是直接new 一个static的常量,后者是在一个代码块里new。
2,饿汉式和懒汉式的区别也是一个先new一个后new。
由于饿汉式在多线程的时候是不安全的,所以有了一下的解决方法
5,双重检验的方法
public class E双重检查 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Singleton3 instance= Singleton3.getInstance();
Singleton3 instance1= Singleton3.getInstance();
System.out.println(instance.hashCode());
System.out.println(instance1.hashCode());
}
}
class Singleton3{
//本类内部创建对象实例
private static volatile Singleton3 singleton;
private Singleton3() {
System.out.println("双重检查实现:Db连接成功");
System.out.println();
}
//双重检查
public static Singleton3 getInstance() {
if(singleton==null) {
synchronized (Singleton3.class) {
if(singleton==null) {
singleton=new Singleton3();
}
}
}
return singleton;
}
}
6,静态内部类的方法
public class F静态内部类 {
public static void main(String[] args) {
// TODO Auto-generated method stub
//Singleton4 instance=
Singleton4.getInstance();
//Singleton4 instance1= Singleton4.getInstance();
//System.out.println(instance.hashCode());
//System.out.println(instance1.hashCode());
}
}
class Singleton4{
//private Singleton4() {}
//一个静态内部类,该类中有一个静态属性Singleton4
//类装载
private static class Db{
private final static Singleton4 instance= new Singleton4();
}
//构造私有化,输出连接成功
private Singleton4() {
System.out.println("静态内部类实现:Db连接成功");
System.out.println();
}
//提供一个静态 的共有方法,直接返回Db.instance
public static Singleton4 getInstance() {
return Db.instance;
}
}
7,枚举的方法
public class G枚举 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Singleton5 instance=Singleton5.INSTANCE;
instance.Db();
//Singleton4 instance1= Singleton4.getInstance();
//System.out.println(instance.hashCode());
//System.out.println(instance1.hashCode());
}
}
enum Singleton5{
INSTANCE;//属性\
public void Db() {
System.out.println("枚举实现:Db连接成功");
System.out.println();
}
}
建议
多线程的时候懒汉式会造成线程不安全,所以不建议使用3,4