问题
So I've implemented my own Object Pool Pattern and it works just fine and as expected. Returning my "Teacher" objects from a list and creating them when there aren't any.
My question: The object being returned "Teacher" then needs to be casted into one of its sub classes which is specialised e.g. "Biology-Teacher".
What is the best way to get this kind of functionality?
Edit: Sorry, I didn't think code was needed but here goes.
Below is the casting I was talking about. This throws a run-time exception which is my main problem.
final Bio-Teacher = (Bio-Teacher) ObjectPool.getTeacher();
This is the code inside of my getTeacher() method.
if (objectPool.size() > 0) {
System.out.println("Object returned from list");
return ObjectPool.remove(0);
} else {
System.out.println("Object made and returned");
return new Teacher();
}
At the moment the only objects in the pool are "Teachers" so I only need to check if there are any in the pool. Note: I'm not keeping track of the objects in use, just the ones in my pool, its part of the requirements but I appreciate the advice.
回答1:
Consider having multiple object pools depending on what you want to get back. What if you had the package structure of (and forgive me for the naming):
com.foo.bar.AbstractTeacher
com.foo.bar.Teacher // A factory
com.foo.bar.BioTeacher
com.foo.bar.PhysicsTeacher
...
Each of these classes maintains its own object pool. BioTeacher contains just BioTeacher, while Teacher contains all the Teacher objects
Thus, you would then have code such as:
Teacher t = Teacher.getTeacher();
BioTeacher b = BioTeacher.getTeacher();
This would simplify the casting from the more generic pool as you can specify what type of teacher you want before getting one (though yes, it does make the synchronization between the Teacher class and the BioTeacher class pools more complex).
The way this would be approached by making package level methods (they can be called by other classes in the same package (notice how all the classes are in com.foo.bar
), and unable to be called by objects outside of that package.
Filling the pool would be done with either
Teacher.createTeacher(BioTeacher.class)
Which would then register the teacher in the BioTeacher pool or:
BioTeacher.createTeacher()
Which would then register the teacher in the Teacher pool.
The tricky part if working in a multithreaded environment (something to keep in mind as this is a learning experience is in the methods Teacher.getTeacher()
and BioTeacher.getTeacher()
where one would possibly have a race condition where one thread gets the Teacher from getTeacher while another thread gets one from the BioTeacher.
Another approach to this (forget about the stuff of multiple constructors from above) is to maintain a map of Class,List<Teacher>
within the Teacher
class itself. When you ask for a teacher (Teacher.getTeacher(Teacher.class)
or Teacher.getTeacher(BioTeacher.class)
) you look it up in the map and return an item from the appropriate list. Furthermore, in this method (that can be synchronized) you can then find the teacher in the other list (it will always be in at least two lists (Teacher.class and BioTeacher.class)) and remove it from that list too.
Then you can make the code so that:
BioTeacher Teacher.getTeacher(BioTeacher.class)
works without additional castings. Again, this is a learning experience and will get you into learning more about Java's generics. (More about this approach at How do I return an instance of an object of the same type as the class passed in using Java 6? )
回答2:
Are you are doing this as a learning exercise?
If so, o.k., but object pools, with very few exceptions, are a bad idea and harm performance. See Java Concurrency in Practice section 11.4.7 "Just say no to object pooling.". Or see Performance Myths Revisited. Oops- original link fails, try this one.
(Added). As for your question, don't think you can do it. Imagine if BiologyTeacher had extra fields not in Teacher or HistoryTeacher. They are different sizes - how could the memory be reused?
回答3:
If your Object Pool is actually returning instances of type Bio-Teacher, then yes
Teacher t = ObjectPool.getTeacher();
if (t instanceof Bio-Teacher) {
final Bio-Teacher bioTeacher = (Bio-Teacher) t;
// do something with the Bio-Teacher.
} else {
// do something with Teacher t (and Teacher t is not a Bio-Teacher).
}
You might also try adding a Bio-Teacher constructor that takes a Teacher
and then you could
Bio-Teacher t = new Bio-Teacher(ObjectPool.getTeacher());
来源:https://stackoverflow.com/questions/20233780/object-pool-pattern-in-java