Don't static members make classes kind of (glo

2020-07-17 08:22发布

问题:

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?

回答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?).

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.

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.



回答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#)?

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.



回答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

Data.INSTANCE.GetThing(42);

etc. It's just like Highlander... THERE CAN ONLY BE ONE