Every time I come across an implementation of the singleton pattern or any static classes (i.e. classes with (almost) only static members) I wonder whether this isn't actually a hack and therefore heavy abuse of the principle of classes and instances just to design single objects instead of designing classes and creating a single instance. To me, it looks like static members of classes in general try to add some sort of characteristics to classes which they actually aren't supposed to have and which rather make them object themselves.
每次我遇到单例模式或任何静态类的实现(即具有(几乎)只有静态成员的类)时,我想知道这是不是实际上是一个黑客,因此严重滥用类和实例的原则只是为了设计单个对象,而不是设计类和创建单个实例。对我来说,它看起来像类的静态成员一般尝试向它们实际上不应该具有的类添加某种特性,而是让它们自己对象。
But is it really desirable to have single objects implemented like that? Or do you see things completely differently and don't think that such static classes or singletons have anything in common with actual objects?
但是,实现这样的单个对象真的很可取吗?或者您是否完全不同地看待事物,并且不认为这些静态类或单例与实际对象有任何共同之处?
5 个解决方案
#1
Static members are effectively just namespacing for globals, yes. Nothing wrong with that; namespacing is good, and globals are the cleanest way to accomplish some tasks.
静态成员实际上只是全局变量的命名空间,是的。没有错;命名空间很好,全局变量是完成某些任务最干净的方法。
Singletons can be somewhat more interesting (load on demand...) but they're a similar construct (yeah, you could think of a static member as an anonymous singleton managed by the compiler).
单身人士可能会更有趣(按需加载......)但它们是一个类似的结构(是的,你可以把静态成员看作是由编译器管理的匿名单身人士)。
Like most things, these tools have their place, and only the ideologues worry about whether or not they "fit" with a particular ideology.
像大多数事情一样,这些工具都有它们的位置,只有理论家才会担心它们是否“适合”某种特定的意识形态。
#2
Depending on your language, classes are objects. In ruby and java, they're of class Class; in python, I don't remember (subclasses of type?).
根据您的语言,类是对象。在ruby和java中,它们属于Class Class;在python中,我不记得了(类型的子类?)。
In java, you can't avoid putting things on classes. This means you sometimes have to use classes like you would use namespaces and modules. A lot of the static methods on Math are a good example of this. I'd say that having these methods be static makes the best of a bad situation.
在java中,你不能避免把东西放在类上。这意味着您有时必须使用类似于使用命名空间和模块的类。 Math上的许多静态方法就是一个很好的例子。我会说这些方法是静态的,这是最糟糕的情况。
I think whether it's "dirty" to have static attributes depends very much on the context. What you really should look for is proper encapsulation: it's good if you can draw a curve through the conceptual space of your code and say "everything on this side doesn't need to know anything about things on that side, except for the interface across the curve.
我认为具有静态属性是否“脏”在很大程度上取决于上下文。你真正应该寻找的是适当的封装:如果你能在代码的概念空间中绘制一条曲线并且说“这方面的所有东西都不需要了解那边的东西,除了界面之外的东西,这是很好的。曲线。
#3
You can view it from a performance and memory perspective. For example, in the following code:
您可以从性能和内存的角度查看它。例如,在以下代码中:
public class StringUtils
{
public static boolean isEmpty(String value)
{
// some code
}
public static String reverseString(String value)
{
// some code
}
}
Do you really want to instantiate StringUtils objects all over the place just to call a method that doesn't store any member variables? In a simple program, it doesn't matter much. But once your program starts to get to a certain size and you call these methods thousands of times, well let's just the instantiations can add up. And why? To be a purist? It's not worth the cost. Just use the same instance.
你真的想要在整个地方实例化StringUtils对象只是为了调用一个不存储任何成员变量的方法吗?在一个简单的程序中,它并不重要。但是一旦你的程序开始达到一定的大小并且你将这些方法称为数千次,那么就让实例化可以加起来。为什么?成为纯粹主义者?这不值得花钱。只需使用相同的实例。
#4
Say I have an application which has a single configuration file. How would I create functions to operate on that file without the use of a "singleton" if my language does not support global functions outside of a class (like Java or C#)?
假设我有一个具有单个配置文件的应用程序。如果我的语言不支持类之外的全局函数(如Java或C#),如何在不使用“单例”的情况下创建对该文件进行操作的函数?
It seems to me the only real way to accomplish that is have a singleton class. Using the singleton pattern you also don't need to pass around a pointer to the object, since you can just use the static method to get it again.
在我看来,实现这一目标的唯一真正方法是拥有单例类。使用单例模式您也不需要传递指向对象的指针,因为您可以使用静态方法再次获取它。
I don't see how this is a violation of any OO principles. To do it a different way, like put the configuration functions in another class that doesn't deal with configuration (like a "utility" class) is more of a violation of OO principles.
我不明白这是违反任何OO原则的。要以不同的方式执行此操作,例如将配置函数放在另一个不处理配置的类中(如“实用程序”类)更违反OO原则。
#5
Suppose that you have a multi-threaded application which requires a central data repository. The consumers and producers use or put data in the repository, including the external application object which accesses the repository through an interface.
假设您有一个需要*数据存储库的多线程应用程序。消费者和生产者在存储库中使用或放置数据,包括通过接口访问存储库的外部应用程序对象。
If you made this repository a normal class object, you'd have the problem of initializing it and getting a pointer to every object that needed it. Not the toughest problem, but it can be very confusing with a lot of threads and objects.
如果您将此存储库设置为普通的类对象,则会遇到初始化它并获取指向需要它的每个对象的指针的问题。这不是最棘手的问题,但它可能会让很多线程和对象感到困惑。
On the other hand, if you do this:
另一方面,如果你这样做:
public enum Data implements MyInterface{
INSTANCE;
private final Whatevertype secretstuff = new Whatevertype();
...etc...
public void PutThing( Sometype indata){ ... };
public Sometype GetThing( int somecode ){ ...};
...etc...
}
You (a) don't have to instantiate anything and (b) can access from anywhere with
您(a)不必实例化任何内容,(b)可以从任何地方访问
Data.INSTANCE.GetThing(42);
etc. It's just like Highlander... THERE CAN ONLY BE ONE
它就像汉兰达一样......只能是一个人
#1
Static members are effectively just namespacing for globals, yes. Nothing wrong with that; namespacing is good, and globals are the cleanest way to accomplish some tasks.
静态成员实际上只是全局变量的命名空间,是的。没有错;命名空间很好,全局变量是完成某些任务最干净的方法。
Singletons can be somewhat more interesting (load on demand...) but they're a similar construct (yeah, you could think of a static member as an anonymous singleton managed by the compiler).
单身人士可能会更有趣(按需加载......)但它们是一个类似的结构(是的,你可以把静态成员看作是由编译器管理的匿名单身人士)。
Like most things, these tools have their place, and only the ideologues worry about whether or not they "fit" with a particular ideology.
像大多数事情一样,这些工具都有它们的位置,只有理论家才会担心它们是否“适合”某种特定的意识形态。
#2
Depending on your language, classes are objects. In ruby and java, they're of class Class; in python, I don't remember (subclasses of type?).
根据您的语言,类是对象。在ruby和java中,它们属于Class Class;在python中,我不记得了(类型的子类?)。
In java, you can't avoid putting things on classes. This means you sometimes have to use classes like you would use namespaces and modules. A lot of the static methods on Math are a good example of this. I'd say that having these methods be static makes the best of a bad situation.
在java中,你不能避免把东西放在类上。这意味着您有时必须使用类似于使用命名空间和模块的类。 Math上的许多静态方法就是一个很好的例子。我会说这些方法是静态的,这是最糟糕的情况。
I think whether it's "dirty" to have static attributes depends very much on the context. What you really should look for is proper encapsulation: it's good if you can draw a curve through the conceptual space of your code and say "everything on this side doesn't need to know anything about things on that side, except for the interface across the curve.
我认为具有静态属性是否“脏”在很大程度上取决于上下文。你真正应该寻找的是适当的封装:如果你能在代码的概念空间中绘制一条曲线并且说“这方面的所有东西都不需要了解那边的东西,除了界面之外的东西,这是很好的。曲线。
#3
You can view it from a performance and memory perspective. For example, in the following code:
您可以从性能和内存的角度查看它。例如,在以下代码中:
public class StringUtils
{
public static boolean isEmpty(String value)
{
// some code
}
public static String reverseString(String value)
{
// some code
}
}
Do you really want to instantiate StringUtils objects all over the place just to call a method that doesn't store any member variables? In a simple program, it doesn't matter much. But once your program starts to get to a certain size and you call these methods thousands of times, well let's just the instantiations can add up. And why? To be a purist? It's not worth the cost. Just use the same instance.
你真的想要在整个地方实例化StringUtils对象只是为了调用一个不存储任何成员变量的方法吗?在一个简单的程序中,它并不重要。但是一旦你的程序开始达到一定的大小并且你将这些方法称为数千次,那么就让实例化可以加起来。为什么?成为纯粹主义者?这不值得花钱。只需使用相同的实例。
#4
Say I have an application which has a single configuration file. How would I create functions to operate on that file without the use of a "singleton" if my language does not support global functions outside of a class (like Java or C#)?
假设我有一个具有单个配置文件的应用程序。如果我的语言不支持类之外的全局函数(如Java或C#),如何在不使用“单例”的情况下创建对该文件进行操作的函数?
It seems to me the only real way to accomplish that is have a singleton class. Using the singleton pattern you also don't need to pass around a pointer to the object, since you can just use the static method to get it again.
在我看来,实现这一目标的唯一真正方法是拥有单例类。使用单例模式您也不需要传递指向对象的指针,因为您可以使用静态方法再次获取它。
I don't see how this is a violation of any OO principles. To do it a different way, like put the configuration functions in another class that doesn't deal with configuration (like a "utility" class) is more of a violation of OO principles.
我不明白这是违反任何OO原则的。要以不同的方式执行此操作,例如将配置函数放在另一个不处理配置的类中(如“实用程序”类)更违反OO原则。
#5
Suppose that you have a multi-threaded application which requires a central data repository. The consumers and producers use or put data in the repository, including the external application object which accesses the repository through an interface.
假设您有一个需要*数据存储库的多线程应用程序。消费者和生产者在存储库中使用或放置数据,包括通过接口访问存储库的外部应用程序对象。
If you made this repository a normal class object, you'd have the problem of initializing it and getting a pointer to every object that needed it. Not the toughest problem, but it can be very confusing with a lot of threads and objects.
如果您将此存储库设置为普通的类对象,则会遇到初始化它并获取指向需要它的每个对象的指针的问题。这不是最棘手的问题,但它可能会让很多线程和对象感到困惑。
On the other hand, if you do this:
另一方面,如果你这样做:
public enum Data implements MyInterface{
INSTANCE;
private final Whatevertype secretstuff = new Whatevertype();
...etc...
public void PutThing( Sometype indata){ ... };
public Sometype GetThing( int somecode ){ ...};
...etc...
}
You (a) don't have to instantiate anything and (b) can access from anywhere with
您(a)不必实例化任何内容,(b)可以从任何地方访问
Data.INSTANCE.GetThing(42);
etc. It's just like Highlander... THERE CAN ONLY BE ONE
它就像汉兰达一样......只能是一个人