In what circumstances should I use a Singleton class?
作为此问题的精确副本关闭。但是重新打开,因为其他单例问题是通用的,而不是用于数据库访问。
我在考虑将一个内部数据访问类设为singleton,但是我不能说服自己选择这个类,主要是因为该类除了方法中的局部变量之外没有其他状态。
毕竟,将此类类设计为单例类的目的是什么?它是否保证对数据库的顺序访问,这是不令人信服的,因为大多数现代数据库都可以很好地处理并发性?是否能够重复使用一个可以通过连接池处理的连接?还是通过运行单个实例来节省内存?
请告诉我这一点。
你可能不想在你描述的情况下使用单例。让所有到数据库的连接通过dbd/dbi类型类的单个实例进行,会严重地限制您的请求吞吐量性能。
高温高压
干杯,
抢劫
从"设计模式:可重用面向对象软件的元素"中:
It's important for some classes to
ahve exactly one instance. Although
there can be many printers in a
system, there should only be one
printer spooler. There should only be
one file system and one window
manager. ...Use the Singleton pattern when:
- there must be exactly one instance of a class, and it must be accessible to clients from a well-known access point
- the sole instance should be extensible by subclassing and clients should be able to use an extended instance without modifying their code
一般来说,在Web开发中,真正应该实现单例模式的只有Web框架本身;您在应用程序中编写的所有代码(一般来说)都应该假设并发性,并依赖数据库或会话状态之类的东西来实现全局(跨用户)行为。
我发现单例模式适用于以下类:
- 无状态
- 充满了基本的"服务会员"
- 必须严格控制资源。
这方面的一个例子是数据访问类。
您将拥有接受参数并返回的方法,比如说,一个DataReader,但是您不会在单例中操纵读卡器的状态,您只需要获取它并返回它。
同时,您可以采用可以在项目之间分布的逻辑(用于数据访问),并将其集成到一个适当管理其资源(数据库连接)的类中,而不管是谁调用它。
尽管如此,singleton是在.NET概念完全静态类之前发明的,所以如果您要走一条或另一条路的话,我就不知道该走哪条路了。事实上,这是一个很好的问题。
这个问题在我想之前就被问过。看看这里
请参阅此问题:关于设计模式:何时使用单例?
如果一个类没有状态,那么它就没有意义成为一个单独的类;所有行为良好的语言最多只能创建一个指向向量表(或等效结构)的指针来分派方法。
如果有实例状态在类的实例之间可能有所不同,那么单例模式将不起作用;您需要多个实例。
因此,由于穷尽,单例应用的唯一情况是,在所有访问器之间必须共享状态,并且只有在所有访问器之间必须共享状态。
有几件事可以导致类似单件的事情:
- 工厂模式:您构建返回一个对象,使用共享状态。
- 资源池:您共享了一些有限资源表,就像数据库连接一样,必须在一大群人中管理用户。(bumbo版本是有一个数据库连接由单身汉
- 外部的并发控制资源;信号量通常是它将是单子的变体,因为P/V操作必须原子地修改共享计数器。
作为一个例子,对象工厂通常是单例的很好的候选者。
您有一个要创建一次的存储库层,该引用在其他地方都使用。
如果你选择标准单件,会有一个坏的副作用。您基本上会破坏可测试性。所有代码都与单例实例紧密耦合。现在,您不能在不访问数据库的情况下测试任何代码(这会使单元测试非常复杂)。
我的建议是:
对于一个简单的问题来说,这是一个很大的工作。但你会过得更好。
近年来,由于单元测试的兴起,单件模式已经失去了很多光彩。
单例测试会使单元测试非常困难——如果您只能创建一个实例,那么如何编写需要被测试对象的"新"实例的测试呢?如果一个测试以某种方式修改了这个单例,那么针对同一对象的任何进一步测试都不会真正从一个干净的石板开始。
单子函数也是有问题的,因为它们实际上是全局变量。几周前,我们在办公室遇到了一个线程问题,因为singleton global正在被各种线程修改;开发人员被批准的"模式"所蒙蔽,没有意识到他真正创建的是一个全局变量。
另一个问题是,在某些情况下,很难创建真正的单子。例如,在Java中,如果不能正确地实现可序列化类的EDCOX1 0Ω方法,则可以创建多个实例。
与其创建单一实例,不如考虑提供一个返回实例的静态工厂方法;这至少让您能够在不破坏API的情况下改变主意。
Josh Bloch在有效的Java中对此进行了很好的讨论。
对于只允许类的一个实例,单件是一个有用的设计模式。singleton的目的是控制对象的创建,将数字限制为1,但允许在情况发生变化时灵活地创建更多的对象。因为只有一个单例实例,所以单例的任何实例字段在每个类中只出现一次,就像静态字段一样。
来源:java.sun.com
有了C,我会说单例是不太合适的。单例的大多数使用都可以用静态类更好地解决。注意线程安全是非常重要的,尽管在任何静态的情况下。对于数据库访问,您可能不需要单个连接,如上所述。您最好创建一个连接,并使用内置池。如果愿意,可以创建一个静态方法,该方法返回一个新的连接来减少代码。然而,ORM模式/框架可能更好。
在C 3.5中,扩展方法可能比静态类更合适。