静态类和单例模式之间存在什么实际的区别?
两者都可以在没有实例化的情况下调用,两者都只提供一个“实例”,而且都不是线程安全的。还有其他区别吗?
静态类和单例模式之间存在什么实际的区别?
两者都可以在没有实例化的情况下调用,两者都只提供一个“实例”,而且都不是线程安全的。还有其他区别吗?
当前回答
Singleton类在应用程序生命周期期间提供一个对象(仅一个实例),例如java.lang.Runtime而静态类只提供静态方法,如java.lang.MathJava中的静态方法不能被重写,但Singleton类中定义的方法可以通过扩展来重写。Singleton类能够继承和多态性来扩展基类、实现接口并能够提供不同的实现。而不是静态的。
例如:java.lang.Runtime是java中的Singleton类,调用getRuntime()方法返回与当前java应用程序关联的运行时对象,但确保每个JVM只有一个实例。
其他回答
真正的答案是Jon Skeet在这里的另一个论坛上给出的。
单例允许访问单个已创建实例-该实例(或而是对该实例的引用)可以作为参数传递给其他方法,并视为正常对象静态类只允许静态方法。
从测试角度来看,Singleton是更好的方法。与静态类不同,singleton可以实现接口,您可以使用mock实例并注入它们。
在下面的示例中,我将对此进行说明。假设您有一个使用getPrice()方法的方法isGoodPrice(。
提供getPrice功能的singleton:
public class SupportedVersionSingelton {
private static ICalculator instance = null;
private SupportedVersionSingelton(){
}
public static ICalculator getInstance(){
if(instance == null){
instance = new SupportedVersionSingelton();
}
return instance;
}
@Override
public int getPrice() {
// calculate price logic here
return 0;
}
}
getPrice的使用:
public class Advisor {
public boolean isGoodDeal(){
boolean isGoodDeal = false;
ICalculator supportedVersion = SupportedVersionSingelton.getInstance();
int price = supportedVersion.getPrice();
// logic to determine if price is a good deal.
if(price < 5){
isGoodDeal = true;
}
return isGoodDeal;
}
}
In case you would like to test the method isGoodPrice , with mocking the getPrice() method you could do it by:
Make your singleton implement an interface and inject it.
public interface ICalculator {
int getPrice();
}
最终Singleton实施:
public class SupportedVersionSingelton implements ICalculator {
private static ICalculator instance = null;
private SupportedVersionSingelton(){
}
public static ICalculator getInstance(){
if(instance == null){
instance = new SupportedVersionSingelton();
}
return instance;
}
@Override
public int getPrice() {
return 0;
}
// for testing purpose
public static void setInstance(ICalculator mockObject){
if(instance != null ){
instance = mockObject;
}
测试等级:
public class TestCalculation {
class SupportedVersionDouble implements ICalculator{
@Override
public int getPrice() {
return 1;
}
}
@Before
public void setUp() throws Exception {
ICalculator supportedVersionDouble = new SupportedVersionDouble();
SupportedVersionSingelton.setInstance(supportedVersionDouble);
}
@Test
public void test() {
Advisor advidor = new Advisor();
boolean isGoodDeal = advidor.isGoodDeal();
Assert.assertEquals(isGoodDeal, true);
}
}
如果我们选择使用静态方法来实现getPrice(),那么很难模拟getPrice)。您可以使用power mock模拟静态,但并非所有产品都可以使用它。
延迟加载支持接口,以便提供单独的实现能够返回派生类型(作为lazyloading和接口实现的组合)
正如我所理解的,静态类和非静态Singleton类之间的区别,静态在C#中只是一个非实例化的“类型”,其中Singleton是一个真正的“对象”。换句话说,静态类中的所有静态成员都被分配给该类型,但在Singleton中,这些静态成员都位于对象之下。但请记住,静态类的行为仍然像引用类型,因为它不是Struct那样的值类型。
这意味着当你创建一个Singleton时,因为类本身不是静态的,但它的成员是静态的,所以它的优点是Singleton内部的静态成员(指的是它自己)连接到一个实际的“对象”,而不是一个空的“类型”。这就澄清了静态和非静态Singleton之间的区别,超越了它的其他特性和内存使用,这让我感到困惑。
两者都使用静态成员,它们是成员的单个副本,但Singleton将引用的成员包装在一个真正的实例化“对象”周围,该对象的地址除了静态成员之外还存在。该对象本身具有财产,其中可以传递和引用in,从而增加值。静态类只是一种类型,因此除了指向其静态成员外,它不存在。这个概念某种程度上巩固了Singleton vs Static Class超越继承和其他问题的目的。
单例只是一个被实例化的普通类,但仅从客户端代码间接实例化一次。静态类未实例化。据我所知,静态方法(静态类必须有静态方法)比非静态方法更快。
编辑:FxCop性能规则描述:“不访问实例数据或调用实例方法的方法可以标记为静态(在VB中共享)在这样做之后,编译器将向这些成员发出非虚拟调用点,这将防止在运行时对确保当前对象指针为非空的每个调用进行检查。这可以为性能敏感的代码带来可衡量的性能增益。在某些情况下,无法访问当前对象实例表示正确性问题。"我不知道这是否也适用于静态类中的静态方法。