ASPN ActiveState Programmer Network  
ActiveState, a division of Sophos
/ Home / Perl / PHP / Python / Tcl / XSLT /
/ Safari / My ASPN /
Cookbooks | Documentation | Mailing Lists | Modules | News Feeds | Products | User Groups
Submit Recipe
My Recipes

All Recipes
All Cookbooks


View by Category

Title: Singleton? We don't need no stinkin' singleton: the Borg design pattern
Submitter: Alex Martelli (other recipes)
Last Updated: 2001/08/27
Version no: 1.1
Category: OOP

 

4 stars 18 vote(s)


Editors pick

Description:

The Singleton design pattern (DP) has a catchy name, but the wrong focus -- on identity rather than on state. The Borg design pattern has all instances share state instead, and Python makes it, literally, a snap.

Source: Text Source

class Borg:
    __shared_state = {}
    def __init__(self):
        self.__dict__ = self.__shared_state
    # and whatever else you want in your class -- that's all!

Discussion:

The 'Singleton' DP is all about ensuring that just one instance of a certain class is ever created. It has a catchy name and is thus enormously popular, but it's NOT a good idea -- it displays different sorts of problems in different object-models. What we should really WANT, typically, is to let as many instances be created as necessary, BUT all with shared state. Who cares about *identity* -- it's *state* (and behavior) we care about!

You can ensure this in many ways in Python, but the Borg design pattern is almost always best. Since the self.__dict__ of any instance can be re-bound, just re-bind it in __init__ to a class-attribute dictionary -- *that's all*! Now any reference or binding of an instance attribute will actually affect all instances equally -- "we all are one", and all that jazz. Thanks to David Ascher for suggesting the very appropriate name "Borg" for this DP.

Note that __getattr__ and __setattr__ are not involved -- they can be defined independently for whatever other purposes, or left undefined (and __setattr__, if defined, is NOT called for the rebinding of __dict__ itself). This only works with 'classic classes' (all classes in Python 2.1 and earlier, those that don't inherit from built-in types in 2.2 and later), whose instances keep all their per-instance state via self.__dict__ -- 2.2/+ classes with self.__slots__ do not support this idiom quite as smoothly (you can use getters/setters for such advanced-classes to deal with this issue, if you wish, but sticking to 'classic classes' for these needs may be simplest).



Add comment

Number of comments: 28

Another name..., Magnus Lie Hetland, 2001/08/17
How about Hivemind? I've seen that used in science fiction situations that might fit this concept
Add comment

Name suggestion, David Ascher, 2001/08/22
I think the 'Borg' fits this pattern quite well. =)
Add comment

Should just call it a singleton!, Marcus Baker, 2001/08/23
The singleton name is correct, even though your Python implementation is neat++.

In Effective C++ by Scott Meyers (item 47) he solves the singleton problem in exactly the same way. The object is created once and then subsquent calls simply return a reference to the original object. In C++ Meyers uses a function wrapper to ensure that it will be declared early enough, but the principle is the same.

In the Design Patterns book the C++ implementation has a class wide Singleton::Instance() function and prevents the constructor being used by making it protected. Same trick.

Coincidently, in an upcoming PHP cookbook web site I am going to publish a singlton pattern that uses the same trick.

yours, Marcus.
Add comment

It's NOT a singleton object... it doesn't NEED to be!, Alex Martelli, 2001/08/27
This is a completely and deeply different pattern from Singleton, and thus I find the latest comment totally off-base. Singleton focuses (wrongly) on *object IDENTITY*: that's what the Gof4 focuses on, that's what "EffC++" focuses on, etc, etc. But we *don't really care* about identity most of the time, but about *state and behavior*.

The "Borg" design pattern IS quite possible in C++ (just a bit more laborious, but not much) and was indeed once written up in C++ Report (but I forget the name it was given then and can't find my old issue): you get as many objects as you want, with separate identities but all sharing state and behavior. That's the POINT! Just about all the *practical USEFULNESS* of Singleton *without* the troublesome identity-issue that Singleton tends to give.
Add comment

You loose the encapsulation, readability and explicitness offered by the Singleton, dani kenan, 2001/08/27
You have a point with the state thing and all, however you do loose the encapsulation offered by the Singleton pattern. You also loose readability and explicitness.
 
If you take the gof course, your implementation can still return new instances implemented just as you have described.
 
However, if you take your course it will be much difficult (or impossible) to replace the creation of new instances with a single one.
 
Also, you loose the explicitness offered by the gof pattern. Clients know that they use a shared object and that it is – transient – and susceptible to change by others.
 
Your suggestion might lead to serious misunderstandings (i.e. bugs) in clients of the object (and the external interface exposed to the client is more important than the implementation and the implementers).
Add comment

quoting..., Marcus Baker, 2001/08/28
Please calm down.

From GOF4: "...to make the class itself responsible for keeping track of it's sole instance." which does cover your intention.
I probably did not make clear that it was their intention rather than their implementation I was trying to get accross. EffC++ was trying to solve a slightly different problem and recast it as a singleton. It seems pretty clear that both were trying to get around the "new" semantics in their implementations and that your implementation is different. Agreed.

Singleton is a very nice name. Agreed.

Borg is a nice name, but I am not sure that it is exactly right. It could fit a lot of cooperative behaviours as well as "all as one". A thread pool that all worked at the same task would fit.

I could not say which is the more confusing and you will have to just ask lots of programmers as a usability test. I am afraid my personal vote is still for singleton as when I inherit a singleton I know what I want, but when I inherit a Borg I am (a little) less sure.

Please let us know which issue of C++ report it is in when you find it.
yours, Marcus.
Add comment

inheriting singleton vs inheriting borg, Alex Martelli, 2001/09/06
What happens in a large system when two separate subsystems both inherit from (extend) a singleton-class? It's anything but clear to me -- error at runtime, at compiletime, at linktime (none such in Python, let's say at import-time), or what behavior...?

With Borg, it's simplicity itself: as Borg can be instantiated as many times as you want, but all instances share state, each separate subclass may differently override _behavior_, but _state_ will still be collectively shared by all Borg's and sub-Borg's. (Separate sub-Borg classes may of course have class-private state by naming attributes with two leading underscores, as typically done in Python). Easy as pie -- and by that very token, easy to document and explain, too. "All state is shared, identity is indifferent, you'll be assimilated"!-)
Add comment

This discussion ..., Steve Holden, 2001/09/13
... is getting very long and thin (at least in my browser). Perhaps additional remarks could appear in a new thread?
Add comment

Borg vs. Singleton, Nicola Musatti, 2001/09/18
Alex, isn't this pattern the one you once referred to as "Stateless Proxy"? And, Marcus, Borg is similar to Singleton, except that you separate access and functionality. In C++ you'd still have a static instance of the class that provides the *functionality* (no loss of encapsulation, then), but it would be private to the Borg class and would only be accessed by the Borg class's member functions.
Add comment

Borg is indeed 'stateless proxy', Alex Martelli, 2001/09/20
Yes Nicola, Borg is the new and improved name (suggested by David Ascher, chief editor of this Cookbook, in a comment above) for the pattern formerly known as 'stateless proxy'.
Add comment

also known as Monostate, Dale Nagata, 2001/09/30
There was an article in the C++ Report several years ago that introduced the Monostate pattern, where all instances share the same state. The major problem I have found with most implementations of Singletons or Monostates in various languages is that if you need to support multithreading, you have to jump through some fairly major hoops to achieve a good balance of correctness and efficiency.
Add comment

also known as Monostate, Dale Nagata, 2001/09/30
There was an article in the C++ Report several years ago that introduced the Monostate pattern, where all instances share the same state. The major problem I have found with most implementations of Singletons or Monostates in various languages is that if you need to support multithreading, you have to jump through some fairly major hoops to achieve a good balance of correctness and efficiency.
Add comment

threading, Alex Martelli, 2001/10/15
Threading issues really have little to do with Highlander vs Borg (or Singleton vs Monostate if you prefer boring names:-). In Python, it's simplest to devote a thread to handling a bunch of resources that need to be serialized (no matter whether they're wrapped into one or more objects of whatever type), with a Queue of requests on which the devoted-thread (Guardian thread) always sleeps working for requests. All access by working threads to the guardian thread and the resources it protects is by posting to the guardian queue a tuple (response-queue, callable, args, kwds) followed by waiting on the response-queue. Why people would want to conflate this important idiom with the equally important and unrelated idiom of state sharing is a mystery to me, as they work just as well together or separately. What's the contrary of "divide and conquer" -- "conflate and suffer"?-)
Add comment

Borg and more than one module, Jan Wender, 2001/10/11
If you want to use the Borg pattern from more than one module, it works as follows: Extract the Borg Pattern into a module and a class of its own: borg.py:

class Borg:
    __shared_state = {} # or org.python.core.PyStringMap in jython
    def __init__(self):
         self.__dict__ = self.__shared_state
Let your class in a separate module inherit from Borg and call Borg's initializer in your __init__:
import borg
class Test(borg.Borg):
  def __init__(s):
     borg.Borg.__init__(s)
Although sounding like a swedish chef, it works now. The state is shared across all modules using the Test class.
Add comment

Jan Wender, 2001/10/11
Sorry for the replication. Must've hit add instead of preview somewhere...
Add comment

Jan Wender, 2001/10/11
Although it looks now like a bug in the Cookbook code... I'm sure I added the last comment only once!
Add comment

Double comments, andy mckay, 2001/10/15
Sorry there was a bug, its fixed now.
Add comment

what about GC?, Vadim Nasardinov, 2002/09/16
Philosophical considerations aside, the "classic" Singleton pattern would seem to perform better than the Borg pattern, when it comes to garbage collection, wouldn't it? What is the point of having the garbage collector keep track of reference counts for a million objects, when one object would suffice?
Add comment

Singletons using new-style classes, Oren Tirosh, 2002/09/19

class Singleton(object):
    def __new__(type):
        if not '_the_instance' in type.__dict__:
            type._the_instance = object.__new__(type)
        return type._the_instance

Just inherit from this class. Everything else is handled automatically.
Add comment

Slight improvement., Jeff Pitman, 2005/09/21

class Singleton(object):
    def __new__(cls, *p, **k):
        if not '_the_instance' in cls.__dict__:
            cls._the_instance = object.__new__(cls)
        return cls._the_instance
Type is now a keyword. And classes can be initialized with params. This handles that.

Add comment

New-style Borg..., Alex Naanou, 2003/03/12

# here is the new-style Borg (not much more complex then the "old-style")
class Borg(object):
    _state = {}
    def __new__(cls, *p, **k):
        self = object.__new__(cls, *p, **k)
        self.__dict__ = cls._state
        return self

Add comment

Re: New-style Borg..., Jeff Pitman, 2005/09/21
For those just joining us from Google, use Oren Tirosh's in the comment one above. Two instances of this singleton do not pass the id(a) == id(b) test. Oren's does.
Add comment

Singleton is not Borg! :), Alex Naanou, 2007/12/27
Oren's approach is Singleton and I implemented a Borg, there is one fundamental difference: Borg are different objects with shared state and Singleton are One object... this may come useful, in more complex examples, a Borg, for instance, can have partial private namespaces, that is, a namespace that is part private (stored in a particular instance) and part shared, this is harder and less intuitive to do with a Singleton pattern.
Add comment

classes and modules are singletons, Luke Plant, 2005/11/19
You don't need singletons in python simply because classes and modules are always singletons, and they are also first class objects. They can have everything instances have, and as import statements don't make copies there is only ever one of them. We don't need no stinkin' design patterns.
Add comment

Classes and modules are singeltons, but who prevents us?, Andre Pfeuffer, 2006/01/28
I agree, but who prevents us from doing stupid things then? Such as instanciating a class, meant to be a singelton within a modul twice?
Add comment

Classes and modules are singeltons, but who prevents us? : You !, Not specified Not specified, 2006/02/16
Let's suppose you're implementing a singleton-like class, and you create an instance in your module. You don't want anyone else to be able to create another instance of your class. Just remove the class just after having created your instance ! That's all... Exemple (in module singleton) : class MySingleton( object ) : pass singleton = MySingleton() MySingleton = None Then, you can use : from singleton import singleton But you can't do : import singleton singleton.MySingleton() Of course, you can acces to the class threw the instance. But if you're lurking within the instances to find funny things, you'll have problems everywhere...
Add comment

You forgot about type, Alexey Borzenkov, 2007/06/26
Who can prevent someone from doing type(singleton)(...)? I think the real solution could be class with classmethods and __new__ raising an Error, then you don't need no instance. But even then someone could have just replaced __new__. :)
Add comment

simple..., chema quinn, 2007/09/04
If using a class as a singleton, you need http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52304 static methods. You can easily write your __init__ funtion to raise an error.
Add comment



Highest rated recipes:

1. A simple XML-RPC server

2. Web service accessible ...

3. IPy Notify

4. Treat the Win32 Registry ...

5. a friendly mkdir()

6. Wrapping template engine ...

7. Assignment in expression

8. Changing return value ...

9. Implementation of sets ...

10. bag collection class




Privacy Policy | Email Opt-out | Feedback | Syndication
© 2006 ActiveState Software Inc. All rights reserved.