什么是单例?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了什么是单例?相关的知识,希望对你有一定的参考价值。

参考技术A

(1)定义:单例模式的意思就是只有一个实例。单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例。
(2)要点:某个类只能有一个实例;他必须自行创建这个实例;它必须向整个系统提供这个实例;
(3)优点:
** a、实例控制:单例会阻止其他对象实例化其自己的单例对象的副本,从而去报所用对象都访问唯一实例。**
** b、灵活性:以为类控制了实例化过程,所以累可以更加灵活修改实例化过程;**
(4)在Object—C中要实现e单例类,至少需要以下四个步骤:
** a、为单例对象实现一个静态实例,并初始化,然后设置为nil;**
** b、事项里一个实例构造方法检查上面声明的静态实例是否为nil,如果是则新建并返回一个本类的实例;**
** c、重写allocWithZone方法,用来保证其他人直接室友alloc和init视图获得一个新实例的时候不产生一个新实例;**
** d、适当实现allocWithZone,copyWithZone。release和autorelease。**
参考: http://www.cnblogs.com/lyanet/archive/2013/01/11/2856468.html

(1)单例模式是ios中常用的一种设计模式。单例模式是一个雷在系统中只用一个实例对象。通过全局的一个入口点对这个实例对象进行访问;
(2)在程序中,单例模式经常用于只希望一个类中有一个实例,而不运行一个类还有两个以上的实例。当然,在iOS SDK中,根据特定的需求,有些类不仅提供了单例访问的接口,还为开发者提供了实例化一个新的对象那个接口,例如:NSFileManager可以通过defaultManager方法返回想你通的一个NSFileManager对象,如果需要新的一个NSFileManager实例对象,可以通过init方法;
(3)iOS中单例模式的实现方式一般分为两种:Non_ARC(非ARC)和ARC+GCD。

什么是单例的替代品

【中文标题】什么是单例的替代品【英文标题】:What's Alternative to Singleton 【发布时间】:2010-11-21 00:02:28 【问题描述】:

我们有一个类来保存应用程序的配置信息。它曾经是一个单身人士。经过一些架构审查后,我们被告知要删除单例。我们确实看到了在单元测试中不使用单例的一些好处,因为我们可以同时测试不同的配置。

如果没有单例,我们必须在代码中到处传递实例。它变得如此混乱,所以我们编写了一个单例包装器。现在我们将相同的代码移植到 PHP 和 .NET,我想知道是否有更好的模式可以用于配置对象。

【问题讨论】:

【参考方案1】:

仅包含静态方法和字段的类是否可行?我不确定您的具体情况,但可能值得研究。

【讨论】:

如果类是无状态的,应该是静态类。 它在 C++ 中 - 该模式被称为 Monostate。【参考方案2】:

最好的方法是改用工厂模式。当您构造类的新实例(在工厂中)时,您可以将“全局”数据插入到新构造的对象中,作为对单个实例(存储在工厂类中)的引用或通过复制相关数据到新对象中。

然后,您的所有对象都将包含曾经存在于单例中的数据。我认为总体上没有太大区别,但它可以使您的代码更易于阅读。

【讨论】:

我不同意“最佳方式”的说法,但 +1 是一个不错的选择。 这种方法的问题是每个新对象都包含(或引用)可能是大量数据的数据。 var_dump() 在任何这些包含 gob 的对象上都会很快产生大量列表,其中包含 recursion 警告。它非常丑陋,效率不高,而且让事情看起来很混乱。但是,我个人还没有找到更好的方法。我确实将“工厂”方法转变为使用 __construct() 来引用全局。然而,为了避免可怕的单身人士,感觉一切都向后弯曲...... @EastGhostCom:我们不妨使用单例,不要再为难自己了:)【参考方案3】:

我可能会在这里说明显而易见的问题,但是您是否有理由不能使用诸如 Spring 或 Guice 之类的依赖注入框架? (我相信 Spring 现在也可用于 .NET)。

这样,框架可以保存配置对象的单个副本,并且您的 bean(服务、DAO 等)不必担心查找它。

这是我通常采取的方法!

【讨论】:

【参考方案4】:

也许也不是很干净,但您可以将想要更改的信息位传递给创建单例的方法——而不是使用

public static Singleton getInstance() 
    if(singleton != null)
        createSingleton();
        return singleton;
    

您可以在应用程序启动时(以及在单元测试的 setUp-Methods 中)直接调用 createSingleton(Information info)

【讨论】:

【参考方案5】:

如果你使用Spring Framework,你可以创建一个普通的bean。默认情况下(或者如果您显式设置scope="singleton")只创建一个bean 实例,并且每次在依赖项中使用该bean 或通过getBean() 检索该bean 时都会返回该实例。

您可以获得单实例的优势,而无需耦合单例模式。

【讨论】:

哦,讽刺的是 - 使用(单例)Spring bean 来代替您的单例...【参考方案6】:

Google Testing blog 有一系列关于避免 Singleton 的条目(为了创建可测试的代码)。也许这可以帮助你:

Using dependency injection to avoid singletons Singletons are Pathological Liars Root Cause of Singletons Where have all the Singletons Gone?

上一篇文章详细解释了如何将新对象的创建移动到工厂中,这样可以避免使用单例。值得一读。

简而言之,我们将所有新操作员转移到工厂。 我们将所有具有相似生命周期的对象分组到一个工厂中。

【讨论】:

*** 使用依赖注入避免单例 这些文章和谷歌C++编程标准一样好! 嗯,不是真的。例如,“不要使用静态方法”的建议直接违背了 Scott Meyers / Herb Sutters 的最小接口原则。有一些有用的建议,但它们缺乏多种思想的贡献。 @FrankS 为什么你改变了链接的顺序?起初它的时间顺序很好。 @Cawas 其实不知道,那是四年多以前的事了,所以我想我当时有一些原因:-)【参考方案7】:

取决于正在使用的工具/框架等。 使用依赖注入/ioc 工具,通常仍然可以通过让 di/ioc 容器对所需的类(例如 IConfigSettings 接口)使用单例行为来获得单例性能/优化,方法是只创建类的一个实例。这仍然可以代替测试

或者,可以使用工厂来创建类并在每次请求时返回相同的实例 - 但为了测试它可能会返回一个存根/模拟版本

【讨论】:

【参考方案8】:

另一种方法是传入你需要的东西,而不是向对象索要东西。

【讨论】:

【参考方案9】:

查看将配置作为回调接口的可能性。 因此,您的配置敏感代码将如下所示:

MyReuseCode.Configure(IConfiguration)

系统初始化代码如下:

Library.init(MyIConfigurationImpl)

【讨论】:

【参考方案10】:

不要对单个配置对象累积责任,因为它会以一个既难以理解又脆弱的非常大的对象结束。

例如,如果您需要一个特定类的另一个参数,您可以更改Configuration 对象,然后重新编译所有使用它的类。这有点问题。

尝试重构您的代码以避免一个通用的、全局的和大的Configuration 对象。只将必需的参数传递给客户端类:

class Server 

    int port;

    Server(Configuration config) 
        this.port = config.getServerPort();
     


应该重构为:

 class Server 

    public Server(int port) 
       this.port = port;
    
 

依赖注入框架在这里会有很大帮助,但不是必须的。

【讨论】:

是的,这真的很好。我以前做过。我的大配置对象实现了 MailServiceConf、ServerConf 等接口,而依赖注入框架将配置传递给类,因此我的类不依赖于大配置对象。【参考方案11】:

您可以使用依赖注入框架来减轻传递配置对象的痛苦。一个不错的是ninject,它的优点是使用代码而不是xml。

【讨论】:

【参考方案12】:

您可以使用静态方法完成与单例相同的行为。 Steve yegge 在this 帖子中解释得很好。

【讨论】:

其实这篇文章还是不错的,并没有说应该改用静态方法。相反,他说静态方法也只是单例,最后他建议使用工厂方法模式:“我最后说,如果您仍然觉得需要使用单例对象,请考虑使用工厂方法模式。 ...”【参考方案13】:

单例并不邪恶,但设计模式有缺陷。我有一个类,我只想在运行时创建它的单个实例,但想在单元测试期间创建多个隔离实例以确保确定性结果。

使用 Spring 等的 DI 是一个很好的选择,但不是唯一的选择。

【讨论】:

以上是关于什么是单例?的主要内容,如果未能解决你的问题,请参考以下文章

什么是单例设计模式

spring为啥是单例模式

什么是单例模式

spring自动注入是单例还是多例?单例如何注入多例?

什么是单例模式

清晨尝鲜,什么是单例模式?