John
John

Reputation: 23

Create multiple instances of a class, but keep them unique based on a specific attribute (multiple "singletons")

I'm rather new to Java and struggling about following:

I have a class that creates objects, in which different data (lists) are kept. The data is always assigned to one very identifier (attribute):

class History {
    private String identifier;

    private ArrayList<ObjectsRelatedToIdentifier> objectsRelatedToIdentifier;
}

I now need to have one object per identifier (X, Y, Z, etc.) but only one. It should not be possible to instantiate two objects with identifier X.

Also, i need to be able to access those objects from other objects. How do I keep "hold" of them?

The internals of those objects is always the same, only the identifier is different and of course the values in the ArrayList.

Is there some kind of "multiple singleton pattern" or a combination of different patterns?

Upvotes: 2

Views: 751

Answers (5)

Just follow the singleton pattern but, instead of having just one reference to the common object, keep a map of references indexed by the identifier.

public class MultiSingle {

    public static MultiSingle getInstance(String id)
    {
        MultiSingle ret = id2obj.get(id);
        if(ret == null)
        {
            ret = new MultiSingle();
            id2obj.put(id,ret);
        }
        return ret;
    }

    private MultiSingle()
    {
        //Your stuff 
    }

    private static Map<String, MultiSingle> id2obj = new HashMap<>();

}

Upvotes: 1

Stefano Sanfilippo
Stefano Sanfilippo

Reputation: 33076

Use a factory to create objects and have it track all the values.

First make the constructor package local:

public class YourObject {
    private String uniqueValue;

    YourObject(String id) {
        this.uniqueValue = id;
    }
}

Then have others instance the object using YourObjectFactory::create:

public final class YourObjectFactory {
    private static Map<String, YourObject> instances = new HashMap<>();

    public static synchronized YourObject create(String id) {
        YourObject oldInstance = instances.get(id);

        if (oldInstance == null) {
            YourObject newInstance = new YourObject(id);
            instances.put(id, newInstance);
            return newInstance;
        } else {
            return oldInstance;
        }
    }
}

like with:

YourObject woah = YourObjectFactory.create("Woah!");

In this implementation, a reference to the instance will be returned if it was already created for a given id. You can raise an exception instead if you deem it more appropriate.

Upvotes: 0

dcastro
dcastro

Reputation: 68720

What you want isn't really a singleton, it's more of an Object Pool.

Much like a database Connection Pool. Whenever you try to connec to a database that you've connected to before, you'll get a Connection from the pool. If you try to connect to a new database, a new Connection will be created for you and added to the pool.

Internally, the ConnectionPool (or an HistoryPool) could be implemented with an hash map, that maps the connection string (or, in your case, the identifier) to the connection object (an instance of History).

Upvotes: 0

Elliott Frisch
Elliott Frisch

Reputation: 201497

Is there some kind of "multiple singleton pattern" or a combination of different patterns?

Yes, the multiton pattern. Which (from Wikipedia) is,

In software engineering, the multiton pattern is a design pattern similar to the singleton, which allows only one instance of a class to be created. The multiton pattern expands on the singleton concept to manage a map of named instances as key-value pairs.

Multiton URL Diagram

Upvotes: 1

betteroutthanin
betteroutthanin

Reputation: 7586

Put your History objects into HashMap:

HashMap<String key,History h> map = new HashMap<String key,History h>();
map.put("X",new History());

Upvotes: 1

Related Questions