Objective-C: When to know that you are abusing the

2019-07-22 03:31发布

问题:

So my clients iphone app has balloned from 5 or so classes to over 25 in the last few weeks. With such a large (for the iphone anyway) class structure I've been utilizing the Singleton class for accessing global variables. The problem is that whenever I need to access a variable outside of the class I'm working on, I have a choice of either modifying the code to pass a reference to the variable or just throw it in the singleton. Of course throwing it in the singleton is a lot less code and effort, however, now the singleton is beginning to look like a mish-mosh of unrelated globals.

My question is how appropriate is it to maintain a large singleton object with unrelated global vars and what is generally the "best practice" way of sharing data across classes in a "non-trivial" iphone app?

Many thanks in advance for your advice!

回答1:

I have done a detailed analysis of this problem in the context of a decoupled design. I'll try to summarize my points:

  1. If your Singleton carries a significant global state, don’t use Singleton. This includes persistent storage such as Databases, Files etc.
  2. In cases, where dependency on a Singleton Object is not obvious by the classes name, the dependency should be injected. The need to inject Singleton Instances into classes proves a wrong usage of the pattern (see point 1).
  3. A Singleton’s life-cycle is assumed to be the same as the application’s. Most Singleton implementations are using a lazy-load mechanism to instantiate themselves. This is trivial and their life-cycle is unlikely to change, or else you shouldn’t use Singleton.


回答2:

In general, you shouldn't need many singletons or globals in a project. You didn't give much information on what you're actually doing, though. They're a smell, they're not forbidden.

You may want to look into other approaches. E.g. implement a protocol shared by these classes to transfer certain bits of data across as needed (everyone gets their own copy then), or use bindings/KVO to keep the values synched between these classes.

If you get a mish-mash in a class, it is time to split that class into several classes. If you get lots of small one-ivar-classes that are only used by one or two classes, it's probably better to merge it back into one of these, or to take all the features of these three classes and split them up differently.

Also keep in mind that you don't need to have a singleton. A class already is an (meta-)object of which one instance already exists, so you can just use a class method without an instance. The main motivation for using a Singleton instance over a class is that you can replace a singleton with an instance of its subclass without code written against the superclass having to know (e.g. NeXT probably had different NSWorkspace subclasses for different file systems or platforms).



回答3:

Something you might consider is just putting these values in a dictionary that's owned by the application delegate. What kinds of things are you storing?



回答4:

Apple/NeXT defined numerous singletons, each with its own focus, and usually referred to as a "manager" of something. In some cases, such as NSWorkspace, it would seem that they had trouble figuring this out for themselves.