Jor*_*oba 1708 singleton static design-patterns
静态类和单例模式之间存在什么真实(即实际)差异?
两者都可以在没有实例化的情况下调用,两者都只提供一个"实例",它们都不是线程安全的.还有其他区别吗?
Jon*_*eet 1194
是什么让你说单例或静态方法不是线程安全的?通常两者都应该实现为线程安全的.
单例和一堆静态方法之间的最大区别在于单例可以实现接口(或者从有用的基类派生,尽管根据我的经验这不太常见),所以你可以传递单例,好像它只是"另一个" "实施.
Kez*_*zer 453
真正的答案是Jon Skeet,在另一个论坛上.
单例允许访问单个创建的实例 - 该实例(或者更确切地说,对该实例的引用)可以作为参数传递给其他方法,并作为普通对象处理.
静态类只允许静态方法.
小智 354
interface
使用Singleton类来实现,但是类的静态方法(或者例如C#static class
)不能.小智 144
Singleton模式比静态类有几个优点.首先,单例可以扩展类和实现接口,而静态类不能(它可以扩展类,但不会继承它们的实例成员).单例可以懒惰或异步初始化,而静态类通常在首次加载时初始化,从而导致潜在的类加载器问题.然而,最重要的优点是单例可以多态处理,而不会强迫用户假设只有一个实例.
Xaq*_*ron 69
static
类不应该做任何需要状态的东西,它可以将一堆函数放在一起,即Math
(或Utils
在项目中).因此,班级名称只是给我们一个线索,我们可以在哪里找到这些函数,仅此而已.
Singleton
是我最喜欢的模式,并使用它来管理单点的东西.它比static
类更灵活,可以维持状态.它可以实现接口,从其他类继承并允许继承.
我对之间进行选择的规则static
和singleton
:
如果有一堆功能应该保持在一起,那么static
就是选择.可以实现任何其他需要单独访问某些资源的东西singleton
.
Raj*_*rma 61
静态类: -
您无法创建静态类的实例.
加载包含类的程序或命名空间时,由.NET Framework公共语言运行库(CLR)自动加载.
静态类不能有构造函数.
我们无法将静态类传递给方法.
我们不能将Static类继承到C#中的另一个Static类.
具有所有静态方法的类.
更好的性能(静态方法在编译时绑定)
辛格尔顿: -
您可以创建该对象的一个实例并重用它.
Singleton实例是在用户请求时首次创建的.
Singleton类可以有构造函数.
您可以创建singleton类的对象并将其传递给method.
Singleton类没有说继承的任何限制.
我们可以处理单例类的对象而不是静态类的对象.
方法可以被覆盖.
可以在需要时加载延迟(始终加载静态类).
我们可以实现接口(静态类不能实现接口).
Mor*_*dil 51
静态类是仅具有静态方法的类,对于该类,更好的单词将是"函数".静态类中体现的设计风格纯粹是程序性的.
另一方面,Singleton是OO设计特有的模式.它是一个对象的实例(具有其中固有的所有可能性,例如多态性),具有创建过程,该过程确保在其整个生命周期中只有该特定角色的一个实例.
Don*_*eld 35
在单例模式中,您可以将单例创建为派生类型的实例,但不能使用静态类.
快速示例:
if( useD3D )
IRenderer::instance = new D3DRenderer
else
IRenderer::instance = new OpenGLRenderer
Run Code Online (Sandbox Code Playgroud)
Mik*_*der 25
单例和一组静态方法之间的最大区别在于单例可以实现接口(或者从有用的基类派生,尽管这不常见于IME),因此您可以传递单例,就好像它只是"另一个"实现一样.
单元测试课程时,单身人士更容易使用.无论您将单例作为参数(构造函数,设置器或方法)传递,您都可以替换单例的模拟或存根版本.
Jac*_*Dev 23
这是一篇很好的文章: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");
}
}
Run Code Online (Sandbox Code Playgroud)总之,我只使用静态类来保存util方法,并将Singleton用于其他所有方法.
编辑
静态类也是延迟加载的.谢谢@jmoreno(静态类初始化何时发生?)
隐藏静态类的方法.谢谢@MaxPeng.
Pet*_*uza 18
我不是一个伟大的OO理论家,但据我所知,我认为静态类与Singletons相比缺乏的唯一OO特性是多态性.但是如果你不需要它,使用静态类,你当然可以继承(不确定接口实现)和数据和函数封装.
Morendil的评论,"静态类中体现的设计风格纯粹是程序性的"我可能错了,但我不同意.在静态方法中,您可以访问静态成员,这与访问其单个实例成员的单例方法完全相同.
编辑:
我现在实际上在想,另一个区别是静态类在程序启动时被实例化*并且在程序的整个生命周期中存在,而单例在某个时刻被显式实例化并且也可以被销毁.
*或者它可能会在第一次使用时被实例化,具体取决于语言,我认为.
dev*_*747 17
为了说明Jon的观点,如果Logger是一个静态类,则无法完成下面显示的内容.该类SomeClass
需要将ILogger
实现的实例传递给它的构造函数.
Singleton类对于依赖注入是很重要的.
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();
}
}
Run Code Online (Sandbox Code Playgroud)
agn*_*zka 13
单例只是一个正常的类,它被实例化,但只是一次,间接来自客户端代码.静态类未实例化.据我所知,静态方法(静态类必须有静态方法)比非静态方法快.
编辑:
FxCop性能规则描述:"不访问实例数据或调用实例方法的方法可以标记为静态(在VB中共享).执行此操作后,编译器将向这些成员发出非虚拟调用站点,这将阻止在运行时检查确保当前对象指针为非空的每个调用.这可以为性能敏感的代码带来可测量的性能提升.在某些情况下,访问当前对象实例的失败代表了正确性问题.
我实际上并不知道这是否也适用于静态类中的静态方法.
从测试的角度看,Singleton是更好的方法.与静态类不同,单例可以实现接口,您可以使用模拟实例并注入它们.
在下面的例子中,我将说明这一点.假设您有一个方法isGoodPrice(),它使用方法getPrice()并将getPrice()实现为单例中的方法.
提供getPrice功能的单例:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
使用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();
}
Run Code Online (Sandbox Code Playgroud)
最终的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;
}
Run Code Online (Sandbox Code Playgroud)
考试类:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
如果我们采用静态方法来实现getPrice()的替代方法,那么模拟getPrice()是很困难的.您可以使用power mock来模拟静态,但并非所有产品都可以使用它.
JDK 有单例和静态的例子,一方面java.lang.Math
是带有静态方法的 final 类,另一方面java.lang.Runtime
是单例类。
单例的优点
如果您需要维护状态而不是单例模式是比静态类更好的选择,因为在静态类中维护状态会导致错误,尤其是在并发环境中,这可能导致竞争条件,而没有多个线程进行足够的同步并行修改。
如果单例类是重对象,则可以延迟加载,但静态类没有这样的优势并且总是急切加载。
使用单例,您可以使用继承和多态来扩展基类、实现接口并提供不同的实现。
由于 Java 中的静态方法不能被覆盖,因此它们会导致不灵活。另一方面,您可以通过扩展单例类中定义的方法来覆盖它。
静态类的缺点
静态类的优点
详细描述每一个都太冗长,所以我只放了一篇好文章的链接——关于单身人士,你想知道的一切
我同意这个定义:
" 单个 " 一词在整个应用程序生命周期中表示单个对象,因此范围在应用程序级别.
该静没有任何对象的指针,因此范围是在应用程序域级别.
此外,两者都应该实现为线程安全的.
您可以找到有趣的其他差异:Singleton Pattern与Static Class
主要区别是:
小智 5
以下是静态类和单例之间的一些主要区别:
1.Singleton是一种模式,而不是像static那样的关键字。因此,对于创建静态类,static 关键字就足够了,而在单例的情况下,需要为单例编写逻辑。
2.单例类必须有一个私有的默认实例构造函数,而静态类不能包含任何实例构造函数。
3.静态类既不能实例化,也不能扩展,而单例类可以。
4.静态类是隐式密封的,但单例类必须显式装饰为密封。
5.单例可以实现接口或从另一个类继承,但静态类既不实现接口也不从任何其他类扩展。
6.我们无法使用静态类实现依赖注入,但是使用单例类可以进行DI,因为它可以是接口驱动的。静态类的范围位于应用程序域级别,因为它由 CLR 管理,而单例对象的范围则跨应用程序生命周期。
7.静态类不能有任何析构函数,但单例类可以定义析构函数。
8.单例类实例可以作为参数传递给另一个方法,而静态类则不能,因为它只包含静态成员。
归档时间: |
|
查看次数: |
475110 次 |
最近记录: |