On design patterns: When should I use the singleto

2018-12-31 05:34发布

The glorified global variable - becomes a gloried global class. Some say breaking object-oriented design.

Give me scenarios, other than the good old logger where it makes sense to use the singleton.

18条回答
路过你的时光
2楼-- · 2018-12-31 05:52

Managing a connection (or a pool of connections) to a database.

I would use it also to retrieve and store informations on external configuration files.

查看更多
不再属于我。
3楼-- · 2018-12-31 05:52

Shared resources. Especially in PHP, a database class, a template class, and a global variable depot class. All have to be shared by all modules/classes that are being used throughout the code.

It's a true object usage -> the template class contains the page template that is being built, and it gets shaped, added, changed by modules that are adding to page output. It has to be kept as a single instance so that this can happen, and the same goes for databases. With a shared database singleton, all modules' classes can get access to queries and get them without having to rerun them.

A global variable depot singleton provides you a global, reliable, and easily usable variable depot. It tidies up your code a great lot. Imagine having all configuration values in an array in a singleton like:

$gb->config['hostname']

or having all language values in an array like:

$gb->lang['ENTER_USER']

In the end of running the code for the page, you get, say, a now mature:

$template

Singleton, a $gb singleton that has the lang array for replacing into it, and all output loaded and ready. You just replace them into the keys that are now present in mature template object's page value, and then serve it out to user.

The great advantage of this is you can do ANY post-processing you like on anything. You can pipe all language values to google translate, or another translate service and get them back, and replace them into their places, translated, for example. or, you can replace in page structures, or, content strings, as you want.

查看更多
深知你不懂我心
4楼-- · 2018-12-31 05:53

A practical example of a singleton can be found in Test::Builder, the class which backs just about every modern Perl testing module. The Test::Builder singleton stores and brokers the state and history of the test process (historical test results, counts the number of tests run) as well as things like where the test output is going. These are all necessary to coordinate multiple testing modules, written by different authors, to work together in a single test script.

The history of Test::Builder's singleton is educational. Calling new() always gives you the same object. First, all the data was stored as class variables with nothing in the object itself. This worked until I wanted to test Test::Builder with itself. Then I needed two Test::Builder objects, one setup as a dummy, to capture and test its behavior and output, and one to be the real test object. At that point Test::Builder was refactored into a real object. The singleton object was stored as class data, and new() would always return it. create() was added to make a fresh object and enable testing.

Currently, users are wanting to change some behaviors of Test::Builder in their own module, but leave others alone, while the test history remains in common across all testing modules. What's happening now is the monolithic Test::Builder object is being broken down into smaller pieces (history, output, format...) with a Test::Builder instance collecting them together. Now Test::Builder no longer has to be a singleton. Its components, like history, can be. This pushes the inflexible necessity of a singleton down a level. It gives more flexibility to the user to mix-and-match pieces. The smaller singleton objects can now just store data, with their containing objects deciding how to use it. It even allows a non-Test::Builder class to play along by using the Test::Builder history and output singletons.

Seems to be there's a push and pull between coordination of data and flexibility of behavior which can be mitigated by putting the singleton around just shared data with the smallest amount of behavior as possible to ensure data integrity.

查看更多
深知你不懂我心
5楼-- · 2018-12-31 05:54

On my quest for the truth I discovered that there are actually very few "acceptable" reasons to use a Singleton.

One reason that tends to come up over and over again on the internets is that of a "logging" class (which you mentioned). In this case, a Singleton can be used instead of a single instance of a class because a logging class usually needs to be used over and over again ad nauseam by every class in a project. If every class uses this logging class, dependency injection becomes cumbersome.

Logging is a specific example of an "acceptable" Singleton because it doesn't affect the execution of your code. Disable logging, code execution remains the same. Enable it, same same. Misko puts it in the following way in Root Cause of Singletons, "The information here flows one way: From your application into the logger. Even though loggers are global state, since no information flows from loggers into your application, loggers are acceptable."

I'm sure there are other valid reasons as well. Alex Miller, in "Patterns I Hate", talks of service locators and client side UI's also being possibly "acceptable" choices.

Read more at Singleton I love you, but you're bringing me down.

查看更多
看淡一切
6楼-- · 2018-12-31 05:54

One of the ways you use a singleton is to cover an instance where there must be a single "broker" controlling access to a resource. Singletons are good in loggers because they broker access to, say, a file, which can only be written to exclusively. For something like logging, they provide a way of abstracting away the writes to something like a log file -- you could wrap a caching mechanism to your singleton, etc...

Also think of a situation where you have an application with many windows/threads/etc, but which needs a single point of communication. I once used one to control jobs that I wanted my application to launch. The singleton was responsible for serializing the jobs and displaying their status to any other part of the program which was interested. In this sort of scenario, you can look at a singleton as being sort of like a "server" class running inside your application... HTH

查看更多
栀子花@的思念
7楼-- · 2018-12-31 05:55

It can be very pragmatic to configure specific infrastructure concerns as singletons or global variables. My favourite example of this is Dependency Injection frameworks that make use of singletons to act as a connection point to the framework.

In this case you are taking a dependency on the infrastructure to simplify using the library and avoid unneeded complexity.

查看更多
登录 后发表回答