在Java中实现单例设计模式的有效方法是什么?
当前回答
另一个经常用来反对单态的论点是它们的可测试性问题。出于测试目的,单体不容易被模拟。如果这是一个问题,我想做以下轻微修改:
public class SingletonImpl {
private static SingletonImpl instance;
public static SingletonImpl getInstance() {
if (instance == null) {
instance = new SingletonImpl();
}
return instance;
}
public static void setInstance(SingletonImpl impl) {
instance = impl;
}
public void a() {
System.out.println("Default Method");
}
}
添加的setInstance方法允许在测试期间设置单例类的实体模型实现:
public class SingletonMock extends SingletonImpl {
@Override
public void a() {
System.out.println("Mock Method");
}
}
这也适用于早期初始化方法:
public class SingletonImpl {
private static final SingletonImpl instance = new SingletonImpl();
private static SingletonImpl alt;
public static void setInstance(SingletonImpl inst) {
alt = inst;
}
public static SingletonImpl getInstance() {
if (alt != null) {
return alt;
}
return instance;
}
public void a() {
System.out.println("Default Method");
}
}
public class SingletonMock extends SingletonImpl {
@Override
public void a() {
System.out.println("Mock Method");
}
}
这有一个缺点,就是将此功能也暴露给普通应用程序。其他编写该代码的开发人员可能会尝试使用“setInstance”方法来更改特定函数,从而改变整个应用程序的行为,因此该方法的javadoc中至少应该包含一个良好的警告。
尽管如此,对于模型测试的可能性(当需要时),这种代码暴露可能是可以接受的代价。
其他回答
使用枚举:
public enum Foo {
INSTANCE;
}
乔舒亚·布洛赫(Joshua Bloch)在Google I/O 2008的“有效Java重载”演讲中解释了这种方法:视频链接。另请参见其演示文稿的幻灯片30-32(effecte_java_reloaded.pdf):
实现可串行化Singleton的正确方法公共枚举Elvis{实例;private final String[]收藏夹歌曲={“猎犬”,“心碎酒店”};public void printFavorites(){System.out.println(Arrays.toString(收藏夹歌曲));}}
编辑:“有效Java”的在线部分说:
“这种方法在功能上等同于公共字段方法,只是它更加简洁,免费提供了序列化机制,并且即使在复杂的序列化或反射攻击的情况下也能提供针对多个实例化的铁腕保证。虽然这种方法尚未被广泛采用,但单个元素枚举类型是实现一个公共字段的最佳方式。”英格顿。"
确保你真的需要它。在谷歌上搜索“singleton反模式”,看看反对它的一些论点。
我想这并没有什么本质上的问题,但它只是一种公开某些全局资源/数据的机制,因此请确保这是最好的方法。特别是,我发现依赖注入(DI)更有用,特别是如果您也在使用单元测试,因为DI允许您将模拟资源用于测试目的。
创建单例对象的各种方法:
根据约书亚·布洛赫的说法,埃努姆将是最好的。也可以使用双重检查锁定。甚至可以使用内部静态类。
维基百科有一些单态的例子,也在Java中。Java5实现看起来非常完整,并且是线程安全的(应用了双重检查锁定)。
以下是三种不同的方法
枚举/***使用Java Enum的Singleton模式示例*/公共枚举EasySingleton{实例;}双重检查锁定/延迟加载/***带有双重检查锁定的单线模式示例*/公共类DoubleCheckedLockingSingleton{私有静态易失性DoubleCheckedLockingSingleton INSTANCE;private DoubleCheckedLockingSingleton(){}公共静态DoubleCheckedLockingSingleton getInstance(){如果(INSTANCE==null){synchronized(DoubleCheckedLockingSingleton.class){//双重检查Singleton实例如果(INSTANCE==null){INSTANCE=新的DoubleCheckedLockingSingleton();}}}返回INSTANCE;}}静态工厂方法/***带有静态工厂方法的Singleton模式示例*/公开课Singleton{//在类加载期间初始化private static final Singleton INSTANCE=new Singleton();//防止创建另一个“Singleton”实例私有Singleton(){}公共静态Singleton getSingleton(){返回INSTANCE;}}
推荐文章
- 在流中使用Java 8 foreach循环移动到下一项
- 访问限制:'Application'类型不是API(必需库rt.jar的限制)
- 用Java计算两个日期之间的天数
- 如何配置slf4j-simple
- 在Jar文件中运行类
- 带参数的可运行?
- 我如何得到一个字符串的前n个字符而不检查大小或出界?
- 我可以在Java中设置enum起始值吗?
- Java中的回调函数
- c#和Java中的泛型有什么不同?和模板在c++ ?
- 在Java中,流相对于循环的优势是什么?
- Jersey在未找到InjectionManagerFactory时停止工作
- 在Java流是peek真的只是调试?
- Recyclerview不调用onCreateViewHolder
- 将JSON字符串转换为HashMap