Design patterns 静态类和单例模式之间的区别?
静态类和单例模式之间存在什么真正的(即实际的)区别Design patterns 静态类和单例模式之间的区别?,design-patterns,static,singleton,Design Patterns,Static,Singleton,静态类和单例模式之间存在什么真正的(即实际的)区别 两者都可以在不实例化的情况下调用,都只提供一个“实例”,并且都不是线程安全的。还有其他区别吗?单例是实例化的,只是只有一个实例被实例化过,因此单例中的单例 静态类只能由自身实例化。在singleton模式中,您可以将singleton创建为派生类型的实例,但不能使用静态类 快速示例: if( useD3D ) IRenderer::instance = new D3DRenderer else IRenderer::instan
两者都可以在不实例化的情况下调用,都只提供一个“实例”,并且都不是线程安全的。还有其他区别吗?单例是实例化的,只是只有一个实例被实例化过,因此单例中的单例
静态类只能由自身实例化。在singleton模式中,您可以将singleton创建为派生类型的实例,但不能使用静态类 快速示例:
if( useD3D )
IRenderer::instance = new D3DRenderer
else
IRenderer::instance = new OpenGLRenderer
是什么让你说单例或静态方法都不是线程安全的?通常这两者都应该实现为线程安全
单例和一堆静态方法之间的最大区别在于,单例可以实现接口(或者从有用的基类派生,尽管这在我的经验中不太常见),因此您可以像传递“另一个”实现一样传递单例。真正的答案是Jon Skeet singleton允许访问单个 已创建实例-该实例(或 而是对该实例的引用) 可以作为参数传递给其他 方法,并作为正常对照 反对 静态类只允许静态 方法
与静态类相比,单例模式有几个优点。首先,单例可以扩展类并实现接口,而静态类不能(它可以扩展类,但不继承它们的实例成员)。单例可以延迟或异步初始化,而静态类通常在首次加载时初始化,这会导致潜在的类装入器问题。然而,最重要的优点是,可以以多态方式处理单例,而不必强迫用户假定只有一个实例。静态类是一个只有静态方法的类,更好的说法是“函数”。静态类中体现的设计风格纯粹是过程性的
另一方面,Singleton是一种特定于OO设计的模式。它是一个对象的实例(具有该对象固有的所有可能性,例如多态性),具有一个创建过程,确保在其整个生命周期中该特定角色只有一个实例。单例只是一个普通的类,只是从客户机代码实例化了一次,而且是间接的。静态类未实例化。 据我所知,静态方法(静态类必须有静态方法)比非静态方法快 编辑:
FxCop性能规则说明: “不访问实例数据或调用实例方法的方法可以标记为静态(在VB中共享)。执行此操作后,编译器将向这些成员发出非虚拟调用站点,这将阻止在运行时对每个调用进行检查,以确保当前对象指针为非空。这可能会导致性能敏感代码获得可测量的性能增益。在某些情况下,无法访问当前对象实例表示错误不透明度问题。”
我不知道这是否也适用于静态类中的静态方法。我不是一个伟大的OO理论家,但据我所知,我认为静态类与单例类相比唯一缺少的OO特性是多态性。 但是,如果您不需要它,使用静态类,您当然可以继承(不确定接口实现)以及数据和函数封装 Morendil的评论,“静态类中体现的设计风格纯粹是程序性的”,我可能错了,但我不同意。 在静态方法中,您可以访问静态成员,这与访问其单实例成员的单实例方法完全相同 编辑:
我现在实际上在想,另一个区别是,静态类在程序开始时被实例化,并贯穿于程序的整个生命周期,而单例在某个点被显式实例化,也可以被销毁
*或者它可能在第一次使用时被实例化,这取决于语言,我认为。静态类不适用于任何需要状态的东西。它有助于将一系列函数放在一起,即
Math
(或项目中的Utils
)。所以类名只是给了我们一个线索,我们可以在哪里找到函数,什么都没有
Singleton
是我最喜欢的模式,我用它在一个点上管理一些东西。它比静态类更灵活,并且可以维护它的状态。它可以实现接口、从其他类继承并允许继承
我在静态
和单例
之间选择的规则:
如果有一组函数应该放在一起,那么选择static
。
任何其他需要单独访问某些资源的内容都可以实现为
单例
单例的另一个优点是它可以很容易地序列化,如果您需要将其状态保存到光盘或远程发送到某处,这可能是必需的
在许多情况下,这两个实例没有实际的区别,特别是如果单例实例从未更改或更改非常缓慢,例如保持配置 我想说的是,最大的区别是,单例仍然是一个普通的Javabean,而不是专门的纯静态Java类。正因为如此,单身在更多的情况下被接受;事实上,这是默认的Spring框架的实例化策略。消费者可能知道也可能不知道这是一个被传递的单例,他们只是把它当作一个普通的JavaBEA
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();
}
}
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;
}
}
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;
}
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);
}
}
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");
}
}