设计模式之单例模式2
单例模式存在的问题
- 单例对 OOP 特性的支持不友好
- 单例会隐藏类之间的依赖关系
- 单例对代码的扩展性不友好
- 单例对代码的可测试性不友好
- 单例不支持有参数的构造函数
如何解决构造参数问题
- 第一种解决思路是:创建完实例之后,再调用 init() 函数传递参数 。确保init函数调用,否则抛出系统异常。
package com.hero.designpatten.singleton;
/**
* @description: Singleton
* @date: 2021/3/2 15:38
* @author: hero
* @version: 1.0
*/
public class SingletonA {
private static SingletonA instance = null;
private final int paramA;
private final int paramB;
private SingletonA(int paramA, int paramB) {
this.paramA = paramA;
this.paramB = paramB;
}
public static SingletonA getInstance() {
if (instance == null) {
throw new RuntimeException("run init() first");
}
return instance;
}
public synchronized static void init(int paramA, int paramB) {
if (instance != null) {
throw new RuntimeException("Singleton has been created");
}
instance = new SingletonA(paramA, paramB);
}
public static void main(String[] args) {
SingletonA.init(10, 50);
SingletonA singletonA = SingletonA.getInstance();
}
}
- 第二种解决思路是:将参数放到 getIntance() 方法中 。原有参数变化时,可以再次创建新的对象,以免误导用户。
package com.hero.designpatten.singleton;
/**
* @description: SingletonB
* @date: 2021/3/2 15:49
* @author: hero
* @version: 1.0
*/
public class SingletonB {
private static SingletonB instance = null;
private int paramA;
private int paramB;
private SingletonB(int paramA, int paramB) {
this.paramA = paramA;
this.paramB = paramB;
}
public static SingletonB getInstance(int paramA, int paramB) {
if (instance == null) {
instance = new SingletonB(paramA, paramB);
}
return instance;
}
public static void main(String[] args) {
SingletonB singletonB1 = SingletonB.getInstance(10, 50);
SingletonB singletonB2 = SingletonB.getInstance(20, 50);
}
}
- 第三种解决思路是:将参数放到另外一个全局变量中。
package com.hero.designpatten.singleton;
/**
* @description: SingletonC 推荐该方式创建单例模式
* @date: 2021/3/2 15:49
* @author: hero
* @version: 1.0
*/
public class SingletonC {
private static SingletonC instance = null;
private int paramA;
private int paramB;
private SingletonC() {
this.paramA = SingletonConfig.PARAM_A;
this.paramB = SingletonConfig.PARAM_B;
}
public synchronized static SingletonC getInstance() {
if (instance == null) {
instance = new SingletonC();
}
return instance;
}
static class SingletonConfig {
public static final int PARAM_A = 123;
public static final int PARAM_B = 245;
}
public static void main(String[] args) {
SingletonC singletonB1 = SingletonC.getInstance();
}
}
静态方法这种实现思路,并不能解决我们之前提到的问题。实际上,它比单例更加不
灵活,比如,它无法支持延迟加载。
实际上,类对象的全局唯一性可以通过多种不同的方式来保证。我们既可以通过单例模式来强制保证,也可以通过工厂模式、IOC 容器(比如 Spring IOC 容器)来保证,还可以通过程序员自己来保证(自己在编写代码的时候自己保证不要创建两个类对象)。