tags:

views:

349

answers:

11

I want to have only 5 instance of a class throughout the application life time. How can I achieve this? Please give sample code, if possible.

+1  A: 

Have a look at the static keyword.

Alberto Zaccagni
A: 

create static field howMany which will be incremented each time when the contructor is called.

When howMany => 5 - dany to create an object.

TBH
+1  A: 
class Sample
{
   private static int i = 0;

   private Sample()
   {
   } 

  public static Sample CreateInstance()
   {
      if(i <5)
      {
          i++;
          return new Sample();
      } 

      else
        throw new Exception("Can not create more then 5 instance of this class");  
   }

}
Amitabh
@Amiabh as the answer above, this will only work if the instances dont get deleted.
InsertNickHere
@InsertNickHere - it will work, even if instances get deleted. Maybe there's a spec where the resources are really consumed (like food) and you want to have the application restarted once the 'factory' is out of stock. You never know, the OP didn't tell.
Andreas_D
+6  A: 

The Factory pattern could be your friend. One (fictional, not threadsafe and thus quite simple) example to illustrate the approach:

public static MartiniFactory {

   private static int olives = 100;  // you asked for '5' but 100 is more realistic
                                     // for this example.

   public static Drink createMartini() throws OutOfOlivesException {
     if (olives > 0) {
       olives--;
       return new Martini(new Gin(4), new Vermouth(1), new Olive());
     else {
       throw new OutOfOlivesException();
     }
   }

   // forgot to mention, only the factory (=bar) is able to create Martinis, so:
   private class Martini {
      Martini(Ingredient... ingredients) {
        // ...
      }
      // ....
   }

}

EDIT

The license example was not too good - so I moved it to a domain that expects, that objects created by the factory are not returned and destroyed without noticing the factory. The Bar can't create Martinis when there is no olive left and it definitly doesn't want the drink back after it has been consumed ;-)

EDIT 2 And for sure, only the factory can create Instances (=Drinks). (No guarantee, that the added inner private class fulfills this requirement, don't have an IDE at hand to do a quick test .. feel free to comment or edit)

Andreas_D
@Andreas_D This will only work it all instances dont get deleted during the programs lifetime. It will need a fully reference counted class, that means, you have also to care about destruction.
InsertNickHere
@InsertNickHere - the specs are pretty vague. This is snippet very, very simplified and a real implementation (based on more detailed specs) might take care of getting resources back or pooling.
Andreas_D
+1 The code (perhaps rightly so) is making an assumption that you would only want to call createMartini() five times. This isn't how a Singleton-style pattern would work. As singleton allows the call as many times as possible, and only created the instance if it hasn't been created (ie on the first call) If you were to allow this method to be called more than five times then there needs to be some kind of strategy for deciding which of the five instances to return. Least recently used? Round robin? Random? It will be application specific as to the correct answer here.
Noel M
@Noel M - I changed the domain. Hope I can keep your +1 ;-)
Andreas_D
@Andreas_D - sure :) I've edited my comment above.
Noel M
Whoa - a downvote - looks like someone doesn't like Martinis ;-))
Andreas_D
Your approach is not thread-safe. You need an AtomicInteger to count down your olives
GHad
@GHad - show me the requirement for thread safety... And of course, it is not portable to C++ and doesn't make use of the Observer pattern... Ah, and no javadoc. So three more downvotes?
Andreas_D
@Andreas_D If your solution is not thread safe, the requirement of five instances per application lifetime can not be fulfilled in generally although not explicit mentioned in the question. Please do not get pissed, this is no competition but a search for the best solution and that includes typical application usage patterns like threading. When your createMartini() method has a race condition, an unknown number of instances may be produced in contrast to the requirement of the question. I did not want to make you angry, but to point you at a design flaw you can correct in an easy way.
GHad
+1 for mentioning The Factory pattern
JLWarlow
+1 for mentioning Martini
kbok
+1 @GHad. If it is not thread safe, then you do not fulfill the requirements.
Lombo
@Lombo - please name the OP's requirement that calls for a thread safe solution.
Andreas_D
@Andreas_D it needs only 5 instances. With this code you can have more than 5.
Lombo
A: 
public class FiveInstance {
    private static int instanceCount = 0;
    private FiveInstance(){
    }
    public static FiveInstance getNewInstance() throws InstanceExceededException{
        if(instanceCount < 5){
            instanceCount++;
            return new FiveInstance();
        }else{
            throw new InstanceExceededException();
        }
    }
}
Bragboy
A: 

Create a private static member to count the instances of the class. Then, make sure every constructor of your class increment this static variable and test for overflow. If you have more than one constructor I suggest that you make one constructor implement this behaviour and the others should call it. The behavior of the constructor upon an attempt to create a sixth instance is up to you. Maybe you want to throw an Exception.

bruno conde
+10  A: 

As Singletons shall be made with enums (See "Effective Java"):

public enum FiveInstance {

  INSTANCE1, INSTANCE2, INSTANCE3, INSTANCE4, INSTANCE5;

  public void anyMethod() {}

}

Greetz GHad

GHad
That's another interpretation of the question ;) Although I'm quite positive that the OP had a factory or a pool in mind. Even if he added the 'Singleton' tag...
Andreas_D
Yes but this approach limits to five instances across application lifetime. And it's threadsafe. A static method to choose from one of the isntances with any algorithm can be added easyly. Greetz, GHad
GHad
I don't understand, @Andreas_D. This seems like exactly the answer to the question asked, and the other high-rated answer looks crazily over-engineered.
Kevin Bourrillion
Honestly, to me this answer here is as useful as Tom Hawtins comment to the question above. Yes, it is threadsafe, but personally I doubt, that the OP can reuse this fragment in his own project. At least you could have shown an example with five *different* instances. Fascinating, how many people consider this a 'useful answer' (because that's the meaning of the upvote button...)
Andreas_D
A: 

You can try following code but written in C#, you can get a basic idea how can it be done.

public  class MultiTone
    {
        private static MultiTone _cache;
        private static int _counter=5;
        MultiTone()
        {

        }
        public static MultiTone GetInstance()
        {
           if(_counter==0)
           {
              return _cache ?? (_cache = new MultiTone());
           }
            _counter--;
            return new MultiTone();
        }
    }

And mind that this class is't intended to use in multi-threading environment.

Int3
Didn't downvote, but: first, a solution in Java langauge was requested and second, it is either a very special requirement or a big surprise for the receiver of the fifth MultiTone that the factory will treat his MultiTone as a pure Singleton (the first four caller get 'private' MultiTones)
Andreas_D
yeah, that was in C#, the code that i provided was not a production code but a basic way of how this can be done. Btw when I started posting a reply there were no any replies but soon i finished, all of them popped up. And thank you for your comment :)
Int3
A: 

I think you can't. You can force that if somebody want to create or destroy an instance has to use these static methods:

import java.util.*;

public class Fiveton {

    public final static int MAX_INSTANCES = 5;

    private static List<Fiveton> instances = new ArrayList<Fiveton>();


    private Fiveton() { }


    public static Fiveton getInstance() {
        if (instances.size()>=MAX_INSTANCES) throw new RuntimeException("Hey! You've reached the maximum of instances: " + MAX_INSTANCES);
        Fiveton instance = new Fiveton();
        instances.add(instance);
        return instance;
    }

    public static void destroy(Fiveton instance) {
        instances.remove(instance);
    }

}

The problem is method destroy. You can't be sure that someone is still referencing the destroyed object.

Sinuhe
Good idea but incomplete - one could call destroy and keep the reference so more then 5 instances of Fiveton could exist. One could add an `invalidate` mechanism to the Fiveton class so that we change the spec to 'only up to five *valid* instances at a time'. And if you keep an invalid Fiveton and try to use it you get nothing but an exception.
Andreas_D
Yes, I'm aware of this problem, and I said it. But I see the same problem in all the others solutions here, and I don't know any solution. Maybe the use of weak or soft references can help, I'll try it at home ;)
Sinuhe
A: 

There is a pattern called a Multiton which deals with this, as an extension of Singleton. Nobody seems quite clear it it's a pattern in its own right or a variation on Singleton. Check out the link, it includes sample code.

John
A: 

Look at Object pool pattern. Its java implementation is greatly described in Grand Patterns in Java V1.

Short description from the book overview:

Object Pool

Manage the reuse of objects for a type of object that is expensive to create or only a limited number of a kind of object can be created.

Roman