静态类和单例模式之间存在什么实际的区别?
两者都可以在没有实例化的情况下调用,两者都只提供一个“实例”,而且都不是线程安全的。还有其他区别吗?
静态类和单例模式之间存在什么实际的区别?
两者都可以在没有实例化的情况下调用,两者都只提供一个“实例”,而且都不是线程安全的。还有其他区别吗?
当前回答
单例只是一个被实例化的普通类,但仅从客户端代码间接实例化一次。静态类未实例化。据我所知,静态方法(静态类必须有静态方法)比非静态方法更快。
编辑:FxCop性能规则描述:“不访问实例数据或调用实例方法的方法可以标记为静态(在VB中共享)在这样做之后,编译器将向这些成员发出非虚拟调用点,这将防止在运行时对确保当前对象指针为非空的每个调用进行检查。这可以为性能敏感的代码带来可衡量的性能增益。在某些情况下,无法访问当前对象实例表示正确性问题。"我不知道这是否也适用于静态类中的静态方法。
其他回答
从测试角度来看,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模拟静态,但并非所有产品都可以使用它。
我们可以创建单例类的对象并将其传递给方法。Singleton类对继承没有任何限制。我们不能处理静态类的对象,但可以处理单例类。
a.序列化-静态成员属于类,因此无法序列化。
虽然我们已经将构造函数私有化,但静态成员变量仍将被携带到子类中。
c.我们不能进行延迟初始化,因为只有在类加载时才会加载所有内容。
下面是静态类和单例之间的一些主要区别:
1.Singleton是一种模式,而不是像static那样的关键字。因此,对于创建静态类,静态关键字就足够了,而对于单例,则需要为单例编写逻辑。
2.单例类必须具有私有的默认实例构造函数,而静态类不能包含任何实例构造函数。
3.静态类既不实例化也不扩展,而单例类可以实例化。
4.静态类是隐式密封的,但单例类必须修饰为显式密封的。
5.单例可以实现接口或从另一个类继承,但静态类既不实现接口,也不从任何其他类扩展。
6.我们不能用静态类实现依赖注入,但单例类可以实现DI,因为它可以是接口驱动的。静态类的作用域位于应用程序域级别,因为它由CLR管理,而单例对象的作用域则跨越应用程序生命周期。
7.静态类不能有任何析构函数,但单例类可以定义析构函数。
8.单例类实例可以作为参数传递给另一个方法,而静态类不能传递,因为它只包含静态成员。
静态类不适用于任何需要状态的对象。它对于将一堆函数放在一起非常有用,例如Math(或项目中的Utils)。所以类名只是给了我们一个线索,我们可以在哪里找到函数,而不是更多。
Singleton是我最喜欢的模式,我用它在一个点上管理一些东西。它比静态类更灵活,可以保持其状态。它可以实现接口,从其他类继承并允许继承。
我在静态和单例之间选择的规则:
如果有一堆函数应该保持在一起,那么静态就是选择。任何其他需要对某些资源进行单一访问的内容都可以作为单例实现。