有ip地址如何做网站成都seo公司
0 引言
创建型模式(Creational Pattern)关注对象的创建过程,是一类最常用的设计模式,每个创建型模式都通过采用不同的解决方案来回答3个问题:创建什么(What),由谁创建(Who)和何时创建(When)。
1 单例模式
单例模式有3个要点:①某个类只能有一个实例;②它必须自行创建这个实例;③它必须自行向整个系统提供这个实例。
单例模式(Singleton),保证一个类仅有一个实例,并提供一个访问它的全局访问点。[DP]
1.1 饿汉单例模式
在类加载的时候就已经实例化,并且创建单例对象,以后直接使用即可。这种模式下,类加载较慢,但获取对象的速度快,且线程安全。
public class HungrySingleton {// 在类加载时就已经完成了实例的初始化private static final HungrySingleton instance = new HungrySingleton();// 构造器私有,防止外部通过new关键字创建对象private HungrySingleton() {}// 提供全局访问点public static HungrySingleton getInstance() {return instance;}// 如果需要,可以添加其他方法或属性public void showMessage() {System.out.println("This is an instance of HungrySingleton.");}public static void main(String[] args) {// 获取单例对象HungrySingleton instance1 = HungrySingleton.getInstance();HungrySingleton instance2 = HungrySingleton.getInstance();// 输出实例,验证是否为同一个对象System.out.println(instance1);System.out.println(instance2);// 验证是否为同一个对象的引用System.out.println(instance1 == instance2);// 调用实例方法instance1.showMessage();}
}
1.2 懒汉单例模式
一开始不会实例化,什么时候用就什么时候进行实例化。这种模式下,类加载较快,但获取对象的速度稍慢,且可能在多线程情况下出现线程安全问题。
存在线程安全问题,
public class LazySingleton {// 私有静态实例,初始化为nullprivate static LazySingleton instance = null;// 私有构造方法,防止外部通过new关键字创建对象private LazySingleton() {}// 提供全局访问点public static LazySingleton getInstance() {if (instance == null) {instance = new LazySingleton();}return instance;}// 如果需要,可以添加其他方法或属性public void showMessage() {System.out.println("This is an instance of LazySingleton.");}public static void main(String[] args) {// 获取单例对象LazySingleton instance1 = LazySingleton.getInstance();// 调用实例方法instance1.showMessage();}
}
加锁,
public class LazySingleton {// 私有静态实例,初始化为nullprivate static LazySingleton instance = null;// 私有构造方法,防止外部通过new关键字创建对象private LazySingleton() {}// 同步方法,提供全局访问点public static synchronized LazySingleton getInstance() {if (instance == null) {instance = new LazySingleton();}return instance;}// 如果需要,可以添加其他方法或属性public void showMessage() {System.out.println("This is an instance of LazySingleton.");}public static void main(String[] args) {// 获取单例对象LazySingleton instance1 = LazySingleton.getInstance();LazySingleton instance2 = LazySingleton.getInstance();// 输出实例,验证是否为同一个对象System.out.println(instance1);System.out.println(instance2);// 验证是否为同一个对象的引用System.out.println(instance1 == instance2);// 调用实例方法instance1.showMessage();}
}
然而,同步方法会导致性能下降,因为每次调用getInstance()方法时都需要进行同步。为了解决这个问题,可以使用双重校验锁(Double-Checked Locking,DCL)来实现更高效的懒汉单例模式:现在这样,我们不用让线程每次都加锁,而只是在实例未被创建的时候再加锁处理。同时也能保证多线程的安全。这种做法被称为Double-Check Locking(双重锁定)。
public class LazySingletonWithDCL {// volatile关键字确保instance在多线程环境下被正确初始化private static volatile LazySingletonWithDCL instance = null;// 私有构造方法,防止外部通过new关键字创建对象private LazySingletonWithDCL() {}// 提供全局访问点public static LazySingletonWithDCL getInstance() {if (instance == null) {// 第一次检查synchronized (LazySingletonWithDCL.class) {if (instance == null) {// 第二次检查instance = new LazySingletonWithDCL();}}}return instance;}// 如果需要,可以添加其他方法或属性public void showMessage() {System.out.println("This is an instance of LazySingletonWithDCL.");}public static void main(String[] args) {// 获取单例对象LazySingletonWithDCL instance1 = LazySingletonWithDCL.getInstance();LazySingletonWithDCL instance2 = LazySingletonWithDCL.getInstance();// 输出实例,验证是否为同一个对象System.out.println(instance1);System.out.println(instance2);// 验证是否为同一个对象的引用System.out.println(instance1 == instance2);// 调用实例方法instance1.showMessage();}
}
使用内部静态类来实现单例模式,这种方式的特点是利用了类加载机制来保证初始化实例时只有一个实例被创建,并且由于JVM的类加载机制,这种方式是线程安全的。只适合java。
public class Singleton {// 私有构造方法,防止外部通过new关键字创建对象private Singleton() {}// 静态内部类,持有单例对象private static class SingletonHolder {// 静态初始化器,由JVM保证线程安全private static final Singleton INSTANCE = new Singleton();}// 提供全局访问点public static Singleton getInstance() {return SingletonHolder.INSTANCE;}// 如果需要,可以添加其他方法或属性public void showMessage() {System.out.println("This is an instance of Singleton.");}public static void main(String[] args) {// 获取单例对象Singleton instance1 = Singleton.getInstance();Singleton instance2 = Singleton.getInstance();// 输出实例,验证是否为同一个对象System.out.println(instance1);System.out.println(instance2);// 验证是否为同一个对象的引用System.out.println(instance1 == instance2);// 调用实例方法instance1.showMessage();}
}