Write a java class to have only five instance of it created
I want to write a java class that can be instantiated only 5 times just like you have singleton class which have only one instance.
Apart from this the instances should be picked in round robin basis.
Suppose I have a class A. I should be only able to create 5 i开发者_运维百科nstances of this class. Say I have InstanceA_1, InstanceA_2, InstanceA_3, InstanceA_4, InstanceA_5. Whenever I need to use them they should be picked on round robin basis.
Just as enum
is recommended by Effective Java 2nd Edition to implement singleton, this solution also uses enum
to implement... quadrupleton?
import java.util.*;
public enum RoundRobin {
EENIE, MEENIE, MINY, MO;
private final static List<RoundRobin> values =
Collections.unmodifiableList(Arrays.asList(values()));
// cache it instead of creating new array every time with values()
private final static int N = values.size();
private static int counter = -1;
public static RoundRobin nextInstance() {
counter = (counter + 1) % N; // % is the remainder operator
return values.get(counter);
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
System.out.println(RoundRobin.nextInstance());
}
// EENIE, MEENIE, MINY, MO, EENIE, MEENIE, MINY, MO, ...
}
}
Extending this to quintupleton is self-explanatory.
See also
- Effective Java 2nd Edition, Enforce singleton property with a private constructor or an enum type
As of release 1.5., there is a third approach to implementing singletons. Simply make an enum type with one element. This approach is functionally equivalent to the public field approach, except that it is more concise, provides serialization mechanism for free, and provides an ironclad guarantee against multiple instantiation, even in the face of sophisticated serialization or reflection attacks. While this approach has yet to be widely adopted, a single-element enum type is the best way to implement a singleton.
Related questions
- Efficient way to implement singleton pattern in Java
You need something like an Object pool. The simplest implementation would be to have a singleton containing a List
of 5 objects, and whenever you call getInstance(..)
, the list should be iterated and one of the objects returned.
Is this a homework?
Why don't you create a Factory that creates 5 instances and store them in a list? When someone calls Factory.getInstance(), it will then get the right instance using the right index of the list.
Would a pool work (e.g. Apache Commons Pool)?
Well, something along these lines:
- Make the constructor private
- Create the five instances in a static initializer, and store the references in an array
- Keep an index to indicate the next one to return
- Write a static method to return the next value and increment the index.
To be thread-safe you will need to lock within the static method. You could use AtomicInteger, but wrapping is tricky. You could always use AtomicInteger
or AtomicLong
, increment each time, and index using the % operator... but when the index wrapped, you'd get a discontinuity. That may or may not be a problem for you.
(This is assuming you don't mind creating all five instances up-front. That certainly makes things easier.)
I imagine that all you would need to do is extend the Singleton pattern to use a counter. Something like...
// Declare a list holding the 5 Objects
List<Foo> instances = new ArrayList<Foo>(5);
// Keep track of which Object you are returning next
int curr = 0;
...
static Foo getInstance() {
// Only instantiate when necessary
if (instances.get(curr) == null) {
instances.set(curr, new Foo());
}
Foo toReturn = instances.get(curr);
// Use modulus to loop back to 0 after 4
curr = (curr + 1) % 5;
return toReturn;
}
Disclaimer: I'm assuming you don't need the code to be thread-safe.
you have to create static instance variable to keep track all your objects.Then you may use an if statement on the constructor to throw an exception or to exit from the system whenever the user initialize the class 5 times.
public class JustFive {
public static int count;
public JustFive(){
if(count>=5){
System.out.println("you can not create another instance");
System.exit(1);
}
else count++;
System.out.println(count);
}}
Youmight want to use static factory mathod. I am showing you the not recommended unusual way.
Here is a very simplistic solution. Note that this isn't thread safe:
class ClassA {
private final List<ClassA> instances = Arrays.asList(new ClassA(), new ClassA(), new ClassA(), new ClassA(), new ClassA());
private ClassA() {}
public static ClassA getInstance() {
Collections.shuffle(instances);
return instances.get(0);
}
}
Create five static instances. Keep an index of the last instance. Make a private constructor. Use a method to get an instance (similar to a singleton);
public class MyObject {
private static final MyObject instance_1 = new MyObject();
private static final MyObject instance_2 = new MyObject();
private static final MyObject instance_3 = new MyObject();
private static final MyObject instance_4 = new MyObject();
private static final MyObject instance_5 = new MyObject();
private static final MyObject[] instances = new MyObject[]{instance_1, instance_2,instance_3, instance_4,instance_5};
private MyObject() {
}
private static volatile int index = 0; //in a multi-threaded evironment, you should use volatile
/**
* The following code is not thread safe
*/
public static MyObject getInstance() {
MyObject instance = instances[index];
if (index == 4) {
index = 0;
} else {
index++;
}
return instance;
}
}
class OnlyFiveTime {
private static LinkedList<OnlyFiveTime> instaces = new LinkedList<OnlyFiveTime>();
private static final int count = 5;
public static OnlyFiveTime getInstace() {
if(instaces.size() != count) {
instaces.addLast(new OnlyFiveTime());
}
OnlyFiveTime robinRound = instaces.removeFirst();
instaces.addLast(robinRound);
return robinRound;
}
private OnlyFiveTime() {
}
}
A simplified RoundRobin.
import java.util.*;
public enum RoundRobin {
EENIE, MEENIE, MINY, MO;
private final static RoundRobin[] values = values();
private static int counter = -1;
public static RoundRobin nextInstance() {
counter = (counter + 1) % values.length;
return values[counter];
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++)
System.out.println(RoundRobin.nextInstance());
// EENIE, MEENIE, MINY, MO, EENIE, MEENIE, MINY, MO, ...
}
}
精彩评论