静态类和单例模式之间的区别?
静态类和单例模式之间存在什么真正的(即实际的)区别?
两者都可以在没有实例化的情况下被调用,都只提供一个“实例”,而且它们都不是线程安全的。 还有其他的区别吗?
是什么让你说,单例或静态方法不是线程安全的? 通常两者都应该被实现为线程安全的。
单身人士和一堆静态方法之间的巨大差别是单身人士可以实现接口(或者从有用的基类派生,虽然这是不常见的,以我的经验),所以你可以绕过单身人士,就好像它是“另一个“实施。
真正的答案是Jon Skeet, 在另一个论坛上 。
单例允许访问单个创build的实例 – 该实例(或者对该实例的引用)可以作为parameter passing给其他方法,并视为普通对象。
静态类只允许静态方法。
- 单例对象存储在堆中 ,但静态对象存储在堆栈中 。
- 我们可以克隆 (如果devise者不禁止它)单例对象,但我们不能克隆静态类对象。
- 单例类遵循OOP (面向对象原则),静态类不遵守。
- 我们可以用一个Singleton类实现一个
interface
,但是一个类的静态方法(或者一个C#static class
)不能。
Singleton模式比静态类有几个优点。 首先,单例可以扩展类并实现接口,而静态类不能(它可以扩展类,但不会inheritance它们的实例成员)。 一个单例可以被初始化为懒惰或asynchronous,而静态类通常在初次加载时被初始化,导致潜在的类加载器问题。 然而,最重要的优点是,单身人士可以被多形地处理,而不会迫使他们的用户假定只有一个实例。
static
类不应该做任何需要状态,它是一起把一堆function,如Math
(或在项目中的Utils
)。 所以class级名称只是给我们一个线索,我们可以findfunction,没有什么更多。
Singleton
是我最喜欢的模式,并用它来pipe理一个点上的东西。 它比static
类更灵活,可以保持状态。 它可以实现接口,从其他类inheritance并允许inheritance。
我的selectstatic
和singleton
规则:
如果有一堆function应该保持在一起,那么static
是select。 其他任何需要单一访问某些资源的东西,都可以用singleton
实现。
静态类只有静态方法,为此,更好的单词是“function”。 静态类中体现的devise风格纯粹是程序性的。
另一方面,Singleton是面向对象devise的特定模式。 它是一个对象的实例(具有所有内在的可能性,例如多态性),创build过程确保在整个生命周期中只有一个特定angular色的实例。
静态类: –
-
您不能创build静态类的实例。
-
当加载包含该类的程序或名称空间时,由.NET Framework公共语言运行库(CLR)自动加载。
-
静态类不能有构造函数。
-
我们不能将静态类传递给方法。
-
我们不能将静态类inheritance到C#中的另一个静态类。
-
一个拥有所有静态方法的类。
-
更好的性能(静态方法在编译时绑定)
辛格尔顿: –
-
您可以创build对象的一个实例并重新使用它。
-
当用户请求时,第一次创build单例实例。
-
Singleton类可以有构造函数。
-
您可以创build单例类的对象并将其传递给方法。
-
Singleton类不会说任何inheritance的限制。
-
我们可以处理单个类的对象,但不能处理静态类的对象。
-
方法可以被覆盖。
-
可以在需要时加载延迟(静态类总是加载)。
-
我们可以实现接口(静态类不能实现接口)。
在单例模式中,你可以创build单例作为派生types的一个实例,你不能用静态类来完成。
快速示例:
if( useD3D ) IRenderer::instance = new D3DRenderer else IRenderer::instance = new OpenGLRenderer
扩展Jon Skeet的答案
单例和一堆静态方法之间的巨大差别是单例可以实现接口(或者从有用的基类派生,尽pipe这不是常见的IME),所以你可以像单纯的“实现”一样传递单例。
unit testing课程时,单身人士更容易使用。 无论你将singleton作为parameter passing(构造函数,设置函数还是方法),都可以replace单例的模拟版本或存根版本。
单身人士的另一个优点是它可以很容易地被序列化,如果你需要将其状态保存到光盘,或者远程发送到某个地方,这可能是必要的。
我不是一个很棒的OO理论家,但是从我所知道的,我认为静态类与Singleton相比缺乏唯一的OO特性是多态性。 但是,如果你不需要它,用一个静态类,你当然可以inheritance(不确定接口实现)和数据和函数封装。
Morendil的评论,“静态类中体现的devise风格纯粹是程序性的”我可能是错的,但我不同意。 在静态方法中,您可以访问静态成员,这与访问其单个实例成员的单例方法完全相同。
编辑:
我实际上在想现在另外一个区别是,一个Static类在程序启动时被实例化 ,并且贯穿程序的整个生命周期,而一个单例在某个时刻被明确地实例化,并且也可以被销毁。
*或者可能会在初次使用时实例化,这取决于语言,我想。
为了说明Jon的观点,如果Logger是一个静态类,那么下面显示的内容是无法完成的。类SomeClass
期望一个ILogger
实现实例被传递到它的构造函数中。
Singleton类对dependency injection是可能的。
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication2 { class Program { static void Main(string[] args) { var someClass = new SomeClass(Logger.GetLogger()); } } public class SomeClass { public SomeClass(ILogger MyLogger) { } } public class Logger : ILogger { private static Logger _logger; private Logger() { } public static Logger GetLogger() { if (_logger==null) { _logger = new Logger(); } return _logger; } public void Log() { } } public interface ILogger { void Log(); } }
这里有一篇很好的文章: http : //javarevisited.blogspot.com.au/2013/03/difference-between-singleton-pattern-vs-static-class-java.html
静态类
- 一个拥有所有静态方法的类。
- 性能更好(静态方法在编译时绑定)
-
不能覆盖方法,但可以使用方法隐藏。 ( 什么是隐藏在Java中的方法?即使JavaDoc的解释也是令人困惑的 )
public class Animal { public static void foo() { System.out.println("Animal"); } } public class Cat extends Animal { public static void foo() { // hides Animal.foo() System.out.println("Cat"); } }
独生子
- 一个只能实例化一次的对象 。
- 方法可以被覆盖( 为什么Java不允许重写静态方法? )
- 更容易模拟静态方法
- 更好地维护国家
总之,我只会使用静态类来保存使用方法,并使用单一的一切。
编辑
-
静态类也被延迟加载。 谢谢@jmoreno( 什么时候静态类初始化发生? )
-
方法隐藏静态类。 谢谢@MaxPeng。
单身人士只是一个普通的类,它被实例化,但是只是一次和间接地从客户端代码中获得。 静态类没有实例化。 据我所知,静态方法(静态类必须有静态方法)比非静态方法更快。
编辑:
FxCop性能规则说明:“不访问实例数据或调用实例方法的方法可以被标记为静态的(在VB中共享),这样做后,编译器会向这些成员发出非虚拟的调用位置,这将阻止在运行时确保当前对象指针是非空的,这可能会导致对性能敏感的代码有一个可测量的性能增益,在某些情况下,访问当前对象实例失败表示一个正确性问题。
我实际上不知道这是否也适用于静态类中的静态方法。
Singleton的实例化,只有一个实例被实例化,因此Singleton中只有一个实例。
一个静态类不能被其他任何东西实例化。
从testing的angular度来看,Singleton是更好的方法。 与静态类不同,singleton可以实现接口,你可以使用模拟实例并注入它们。
在下面的例子中我将说明这一点。 假设你有一个方法isGoodPrice(),它使用方法getPrice(),并且你实现了getPrice()作为一个单身的方法。
提供getPricefunction的单身人士:
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(); }
最终的单例实现:
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; }
testing课:
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()。 你可以用嘲弄的方式嘲弄静态,但并不是所有的产品都可以使用它。
我同意这个定义:
“ 单一 ”一词意味着整个应用程序生命周期中的单个对象,因此范围在应用程序级别。
静态没有任何Object指针,因此范围在App Domain级别。
而且两者都应该被实现为线程安全的。
你可以find有趣的其他区别: 单身模式与静态类
我们有我们的数据库框架,连接到后端。为了避免多个用户的脏读,我们使用单例模式来确保我们在任何时间点都有一个单一的实例。
在C#中一个静态类不能实现一个接口。 当一个实例类需要实现一个业务合约或IoC目的的接口时,这就是我使用Singleton模式而没有静态类的地方
Singleton提供了一种在无状态场景下维护状态的方法
希望能帮到你..
一个显着的区别是随着单例的不同实例化。
使用静态类,它是由CLR创build的,我们没有控制它。 与单身人士,对象得到初始化它试图被访问的第一个实例。
- 懒加载
- 支持接口,以便可以提供单独的实现
- 能够返回派生types(作为延迟加载和接口实现的组合)
在许多情况下,这两者没有实际的区别,特别是如果单例实例永远不会改变或缓慢变化,例如持有configuration。
我想说的最大的区别是单身人士仍然是一个正常的Java Bean反对一个专门的静态Java类。 正因为如此,单身人士在更多的情况下被接受。 它实际上是默认的Spring框架的实例化策略。 消费者可能会也可能不知道它是一个单身人士,它只是把它当作普通的Java bean来对待。 如果需求发生变化,单例需要成为原型,就像我们在Spring中经常看到的那样,它可以完全无缝地完成,而不需要为消费者修改代码。
其他人之前提到过,静态类应该是纯粹的过程,比如java.lang.Math。 在我看来,这样的一个阶级决不应该被传递,他们也不应该持有除静态的最终属性之外的东西。 对于其他任何事情,使用一个单身人士,因为它更灵活,更容易维护。
一个。 序列化 – 静态成员属于这个类,因此不能序列化。
湾 虽然我们已经使构造函数成为私有的,但静态成员variables仍然会被传递给子类。
C。 我们不能做懒惰的初始化,因为所有的东西都只能在类加载时加载。
从客户的angular度来看,静态行为对于客户是已知的,但是单身行为可以从客户隐藏完成。 客户可能永远不会知道,他只有一次他一次又一次地玩弄。
我读了以下内容,并认为它也是有道理的:
照顾业务
请记住,最重要的面向对象规则之一是对象自身负责。 这意味着有关类的生命周期的问题应该在类中处理,而不是委托给静态的语言结构等等。
从“面向对象的思想过程”第4版
- 在C#中一个静态类不能实现一个接口。 当一个实例类需要为了一些商业原因或IoC目的而实现一个接口时,你可以使用没有静态类的Singleton模式。
- 您可以克隆Singleton的对象,但不能克隆静态类对象
- Singleton对象存储在堆中,但静态对象存储在堆栈中
- 单例可以初始化为懒惰或asynchronous,而静态类通常在初次加载时初始化
在我写的一篇文章中,我描述了为什么单例比静态类更好的观点:
- 静态类实际上并不是规范类 – 它是一个带有函数和variables的名称空间
- 由于破坏了面向对象的编程原则,使用静态类并不是一个好的做法
- 静态类不能作为其他parameter passing
- 静态类不适合“惰性”初始化
- 静态类的初始化和使用总是很难被跟踪
- 实现线程pipe理很难
当我想要具有完整function的类时,例如有许多方法和variables,我使用单例;
如果我想只有一个或两个方法的类,例如MailService类,它只有一个方法SendMail()我使用静态类和方法。
There is a huge difference between a single static class instance (that is, a single instance of a class, which happens to be a static or global variable) and a single static pointer to an instance of the class on the heap:
When your application exits, the destructor of the static class instance will be called. That means if you used that static instance as a singleton, your singleton ceased working properly. If there is still code running that uses that singleton, for example in a different thread, that code is likely to crash.
-
We can create the object of singleton class and pass it to method.
-
Singleton class doesn't any restriction of inheritance.
-
We can't dispose the objects of a static class but can singleton class.
As I understand the difference between a Static class and non-Static Singleton class, the static is simply a non-instantiated "type" in C#, where the Singleton is a true "object". In other words, all the static members in a static class are assigned to the type but in the Singleton are housed under the object. But keep in mind, a static class still behaves like a reference type as its not a value type like a Struct.
That means when you create a Singleton, because the class itself isnt static but its member is, the advantage is the static member inside the Singleton that refers to itself is connected to an actual "object" rather than a hollow "type" of itself. That sort of clarifies now the difference between a Static and a Non-Static Singleton beyond its other features and memory usage, which is confusing for me.
Both use static members which are single copies of a member, but the Singleton wraps the referenced member around a true instantiated "object" who's address exists in addition to its static member. That object itself has properties wherein in can be passed around and referenced, adding value. The Static class is just a type so it doesn't exist except to point to its static members. That concept sort of cemented the purpose of the Singleton vs Static Class beyond the inheritance and other issues.