Suggestions on improving this simple object pool class for Java? - java

I am currently writing a game for android where there are enemies that fly across the screen and then disappear, to be replaced by other enemies. Now, this happens very fast, and my code currently performs a lot of memory allocation and deallocation to create and delete these enemy objects, so I'm trying to find a way to optimize this. I got this Pool class implementation from a book on android game dev:
public class Pool<T> {
public interface PoolObjectFactory<T> {
public T createObject();
}
private final List<T> freeObjects;
private final PoolObjectFactory<T> factory;
private int maxObjects;
public Pool(PoolObjectFactory<T> factory, int maxObjects) {
this.maxObjects = maxObjects;
this.factory = factory;
freeObjects = new ArrayList<T>(maxObjects);
}
public T newObject() {
T object = null;
if (freeObjects.isEmpty()) {
object = factory.createObject();
} else {
object = freeObjects.remove(freeObjects.size() - 1);
}
return object;
}
public void free(T object) {
if (freeObjects.size() < maxObjects) freeObjects.add(object);
}
}
Now, the way to use this class is as follows:
PoolObjectFactory<Enemy> factory = new PoolObjectFactory<Enemy>() {
public Enemy createObject() {
return new Enemy();
}
};
Pool<Enemy> enemyPool = new Pool<Enemy>(factory, 50);
The obvious problem with this method is that you can't input any parameters to the createObject() method, thus forcing you to use classes that take no arguments in their constructor. This will force me to rewrite a lot of code since the Enemy class I'm using takes several different parameters. I can think of a couple of workarounds, like this one:
PoolObjectFactory<Enemy> factory = new PoolObjectFactory<Enemy>() {
public Enemy createObject(Object... args) {
return new Enemy((Float)args[0], (Float)args[1]);
}
};
Pool<Enemy> enemyPool = new Pool<Enemy>(factory, 50);
But it's error-prone and annoying to update. I could also initialize the Enemy object in the createObject() method with bogus values and then set them manually later, or I could create a Pool class for every single object but I would really prefer not doing that.
Any suggestions on how to improve this code? How do you fellow java game developers deal with pooling objects to avoid garbage collection? Thanks very much.

1) You should override the createObject function in your PoolObjectFactory.
2) You will need a initialize() function that actually sets the parameters for each EnemyObject. Just have the constructor for the EnemyObject call the initialize function. Then, when you get the object out of the pool, you should just call initialize with your parameters and it should work perfectly.

Related

Is it okay to pass an object to a new object constructor and not use it inside?

Is it okay to pass an object type, or simply a type of any kind into the constructor of a new object then not use it inside of the constructor?
The purpose is to have the new object be created based on what parent class it resides in (it is aggregated) so it generates different variables for itself based on that fact.
Or is there a better way to do this?
public class ObjectA {
private MalleableObject obj;
public void createObject(){
obj = new MalleableObject(this);
}
}
public class ObjectB {
private MalleableObject obj;
public void createObject(){
obj = new MalleableObject(this);
}
}
public class MalleableObject{
private boolean doIBelongToA;
public MalleableObject(ObjectB obj){
doIBelongToA = false;
}
public MalleableObject(ObjectA obj){
doIBelongToA = true;
}
}
The approach you are taking will definitely work, But the question is whether it is a good idea or not, The answer is depends on the use case that you are trying to tackle.
You asked about taking a object as parameter in constructor and not using it
If you are not using the property of passed parameter then why to take that in parameter, for that we have empty constructor , even when you don't specify it is by default injected
public MalleableObject(ObjectB obj){
doIBelongToA = false; // if you are directly setting the value without
//using obj b then use default constructor.
}
public MalleableObject(ObjectA obj){
doIBelongToA = true;
}
/*If you are interested in setting the value based on the reference only there
is no problem with your approach as well, One alternative you can take to
combine both of them in single constructor and check the reference and set
the value accordingly*/
If you use the property of the object for creating new object then certainly it's a good idea,
Copy constructor if you are using same object as parameter, Prototype design pattern if you are creating your object with similiar object already created
The example that you gave is a very basic example which does not highlight any use case and hence the approach you have taken will not be suggested
The simpler approach would be just adding the boolean variable in the constructor of MalleableObject.
public class ObjectA {
private MalleableObject obj;
public void createObject(){
obj = new MalleableObject(true);
}
}
public class ObjectB {
private MalleableObject obj;
public void createObject(){
obj = new MalleableObject(false);
}
}
public class MalleableObject{
private boolean doIBelongToA;
public MalleableObject(boolean doIBelongToA){
this.doIBelongToA = doIBelongToA;
}
}
This would easily assure that the object made from class A has value true for doIBelongToA.
Also, you will not have to add different constructors for further classes, if added, ensuring extensibility
While you aren't using it directly, you are definitely using information from the parameter. Personally, I'd save the reference, or at least its type, for later use in case you need it and implement doIBelongToA as a method, but there's nothing technically wrong with your approach:
public class MalleableObject{
private Class ownerType;
public MalleableObject(Class ownerType) {
this.ownerType = ownerType;
}
public boolean doBelongToA() {
return ownerType.equals(ObjectA.class);
}
}
The above approach works but it's not a best practice and hence has some limitations. I would suggest you use builder pattern where you can create use of a builder to create an object and then have a method that defines the behavior. You will be able to extend this to add variables/business logic in the future.
I think the Factory pattern is also good
thing to look at

Impact of multiple threads using same object in a singleton class

I'm designing a module which can support different datasources.
My module gets the user's company id as inputs and I must call the appropriate class based on the company id.
I'm trying to incorporate some good design and avoid conditional statements where possible.
I have a FetchDataSource singleton class with this method.
public class FetchDataSourceSingleton {
private static Map<String, Communicator> communicatorMap;
public static Communicator getCommunicatorInstance(String dataSourceType) {
if (communicatorMap == null || communicatorMap.isEmpty())
populateCommunicatorMap();
if (communicatorMap.containsKey(dataSourceType))
return communicatorMap.get(dataSourceType);
return null;
}
.... other methods including populateCommunicatorMap()
}
"Communicator" is an interface, and the communicator map will return the appropriate instance.
This is the populateCommunicatorMap() method in the same singleton class.
private static void populateCommunicatorMap() {
communicatorMap = new HashMap<String, Communicator>();
communicatorMap.put("AD", new ADCommunicator());
communicatorMap.put("DB2", new DB2Communicator());
communicatorMap.put("MYSQL", new MYSQLCommunicator());
}
ADCommunicator, DB2Communicator and MYSQLCommunicator will implement the Communicator inteface.
The code seems to work in my test draft.
The only concern I have is the HashMap will return the same object for all communication requests to the same type. I can't seem to avoid having the same instance in the hashmap if I want to avoid the conditional statements. Otherwise instead of the hashmap, I could have just make calls like this.
Communicator comm;
if (type = "AD") comm = new ADCommunicator();
if (type = "DB2") comm = new DB2Communicator();
if (type = "MYSQL") comm = new MYSQLCommunicator();
I've avoided this by using the hashmap to return an instance based on type.
But then I can't avoid the singleton problem where I get the same instance.
In a multithreaded environment, which needs to support hundreds of thousands of communication requests at a time, this could be a problem considering I'll need to syncronize a lot of code in each of the Communicator classes.
Is there a way I can avoid the syncronization and make it thread safe without impacting performance?
I can't seem to avoid having the same instance in the hashmap
You can use a switch instead of a bunch of ifs.
Switch Over an enum (Java 5)
Change type to be an enum in Java 5+, then you can switch on it. I'd recommend enums in general for type safety.
// type is-a enum Communicator.TYPE
switch(type) {
case AD: return new ADCommunicator();
case DB2: return new DB2Communicator();
case MYSQL: return new MYSQLCommunicator();
default: return null;
}
Switch over a String (Java 8)
Java 8 can switch over Strings directly.
// type is-a String
switch(type) {
case "AD": return new ADCommunicator();
case "DB2": return new DB2Communicator();
case "MYSQL": return new MYSQLCommunicator();
default: return null;
}
Switching over an enum will be as fast as a map, if not faster. Switching on the string will be as fast as a Map.
A Map of Factory (factory of factories)
Or have a map of factories:
private final static Map<String, Factory<? extends Communicator>> map;
static {
map.put("AD", ADCommunicatorFactory.getInstance());
//...
map.put(null, NullFactory<Communicator>.getInstance());
} // populated on class-load. Eliminates race from lazy init
// on get
return map.get(type).make();
A Map of Class (reflection)
Or use the reflection API to make instances, but then it would probably be better to just use conditionals.
// on init
Map<String, Class<? extends Communicator>> map = new HashMap<>();
map.put("AD", ADCommunicator.class);
// on get
try {
return (Communicator) map.get(type).newInstance();
} catch(InstantiationException | IllegalAccessException | NullPointerException e) {
return null;
}
P.S.
This all sounds like premature optimization. I doubt that determining which Communicator to use is going to be a bottleneck in your system.
If all your communicators can be constructed with empty argument list constructor, then you can store the type (class) of the communicator in the map instead of an instance. Then you can look up the type (java.lang.Class) from your communicatorMap and instantiate a new instance with java.lang.Class.newInstance().
For example:
public interface Communicator {
void communicate();
}
public class Communicator1 implements Communicator {
public void communicate() {
System.out.println("communicator1 communicates");
}
}
public class Communicator2 implements Communicator {
public void communicate() {
System.out.println("communicator2 communicates");
}
}
public class CommuniicatorTest {
public static void main(String[] args) throws Exception {
Map<String, Class<? extends Communicator>> communicators = new HashMap<String, Class<? extends Communicator>>();
communicators.put("Comm1", Communicator1.class);
communicators.put("Comm2", Communicator2.class);
Communicator comm2 = communicators.get("Comm2").newInstance();
comm2.communicate();
System.out.println("comm2: " + comm2);
Communicator anotherComm2 = communicators.get("Comm2").newInstance();
anotherComm2.communicate();
System.out.println("anotherComm2: " + anotherComm2);
}
}
result:
communicator2 communicates
comm2: pack.Communicator2#6bc7c054
communicator2 communicates
anotherComm2: pack.Communicator2#232204a1
Assylias is correct about using a static initializer. It runs when your class loads, which guarantees that the map will be loaded before anything else happens to the class.
You didn't show the declaration of the map; I assume that it is static.
private final static Map<String, Communicator> communicatorMap;
static {
communicatorMap = new HashMap<>();
communicatorMap.put("AD", new ADCommunicator());
communicatorMap.put("DB2", new DB2Communicator());
communicatorMap.put("MYSQL", new MYSQLCommunicator());
}; // populated on class-load. Eliminates race from lazy init
The remaining issue is the Communicator implementation. All this assumes that it is thread-safe as well.

How to change multiple main variables at the same time in Java

In my understanding of Java, the most common ways to set the instance variables of a class object are:
foo.setFooStuff(bar); // put a setter method inside the class
foo = modifyFooStuff(foo, bar); // pass & return entire object
Let's say my main() has an object of class bigA, which contains a collection of class littleA objects (which contain instance variables), and another object of class bigB, which contains a collection of class littleB objects (which have different instance variables from littleA). How do I write a method to modify instance variables of one or more littleA and littleB objects at the same time?
(Note: I suspect this is a common question, but I searched and didn't find it. Maybe I'm using the wrong terminology.)
Edit: more concrete example: Let's say I'm making Monopoly. A player has money (in various denominations) and properties (some with houses). She wants to upgrade some properties to hotels. Money has to be added and subtracted, as do houses and hotels. I know how to do this in a pass-by-reference language, but not using pass-by-value, unless I make the entire game state into one huge object and pass it around, which seems like a lot of memory shuffling and basically the same as using global variables, which is bad, right?
If I understand your question correctly, you write a method on the bigA/bigB classes that take the value you want to set and then walk the collection of littleA/B objects setting the instance variables as you go. Like:
// Assuming Foo has a member collection of smallFoo
Foo A = new Foo();
// do stuff that populates the collection of smallFoo in A
A.setSmallFooZipCode("23444");
public void setSmallFooZipCode(String zip_ {
// for thisSmallFoo in smallFoo
thisSmallFoo.setZip(zip);
// end for
)
Objects (including your container objects) should represent something--thinking of them in terms of A/B makes this a little tough.
On top of that, if you are always modifying an attribute in two classes at once I'd suggest that's a pretty bad code smell...
Off the top of my head I can't think of anything I'd model this way, so it's hard to come up with an example. Either A and B should be contained in a parent ab class (and that class should have the attribute), or a and b should be the same interface--in either case these would then go into a single collection in a parent container.
So that said, you should have a method on the parent container object that does the work. In most cases it shouldn't be a method like "setAttribute...", it should be a method like "doAction". In other words, if your container is a "Herd" and it contains a bunch of Elephants, then you would tell the Herd to move to a certain location and let the Herd object send a message to each elephant telling it where to go.
If you think of methods in terms of "Asking an object to do something for you" rather than operating on an object, it helps make some of these decisions much easier.
You would simply encapsulate BigA and BigB in another object:
class BigWrapper {
private BigA bigA;
private BigB bigB;
public void someMethod() {
bigA.someMethod();
bigB.someMethod();
}
}
someMethod() within BigA would modify the LittleA instances. Same for BigB:
class BigB {
private LittleA[] littles;
public void someMethod() {
//do something with the littles
}
}
Of course, this solution doesn't allow you to specify which Little instances to target, as well as doesn't allow you to specify which behavior should be performed (which specific method to invoke via the littles).
If you want that flexibility, use callbacks:
interface Little { }
class LittleA implements Little { }
class LittleB implements Little { }
interface Callback<T extends Little> {
void perform(int currentIndex, T currentLittle);
}
class CallbackHandler<T extends Little> {
private int[] indexes;
private Callback<T> callback;
public CallbackHandler(int[] indexes, Callback<T> callback) {
this.indexes = indexes;
this.callback = callback;
}
public void perform(T[] littles) {
for(int i = 0; i < indexes.length; i++) {
int index = indexes[i];
callback.perform(i, littles[index]);
}
}
}
class BigWrapper {
private BigA bigA;
private BigB bigB;
public BigWrapper(BigA bigA, BigB bigB) {
this.bigA = bigA;
this.bigB = bigB;
}
public void perform(CallbackHandler<LittleA> aCallback, CallbackHandler<LittleB> bCallback) {
bigA.perform(aCallback);
bigB.perform(bCallback);
}
}
class BigA {
private LittleA[] littles;
public BigA(LittleA[] littles) {
this.littles = littles;
}
public void perform(CallbackHandler<LittleA> callback) {
callback.perform(littles);
}
}
class BigB {
private LittleB[] littles;
public BigB(LittleB[] littles) {
this.littles = littles;
}
public void perform(CallbackHandler<LittleB> callback) {
callback.perform(littles);
}
}
The CallbackHandler maps the actual callback to the indexes you want to target.
So you would first create the callback:
Callback<LittleA> aCallback = (currentIndex, currentLittle) -> {
//do what you want to the littles
};
Then pass that to a CallbackHandler, which allows you to specify the indexes you wish to target:
int[] indexes = { 0, 1, 2 };
CallbackHandler<LittleA> aCallbackHandler = new CallbackHandler<>(indexes, aCallback);
BigWrapper exposes a perform(CallbackHandler<LittleA>, CallbackHandler<LittleB>), so you would pass the handlers to that method.
An MCVE would look like:
public static void main(String[] args) {
LittleA[] littleA = {
new LittleA(),
new LittleA(),
new LittleA()
};
LittleB[] littleB = {
new LittleB(),
new LittleB(),
new LittleB()
};
BigA bigA = new BigA(littleA);
BigB bigB = new BigB(littleB);
BigWrapper big = new BigWrapper(bigA, bigB);
Callback<LittleA> aCallback = (index, little) -> {
//...
};
Callback<LittleB> bCallback = (index, little) -> {
//...
};
CallbackHandler aCallbackHandler = new CallbackHandler(new int[] { 2, 3, 4 }, aCallback);
CallbackHandler bCallbackHandler = new CallbackHandler(new int[] { 5, 6, 7 }, bCallback);
big.perform(aCallbackHandler, bCallbackHandler);
}

Passing object by reference to a thread

Let's say I have a class called Object and a thread called ObjectCreator that manages the creation of an Object. For the sake of simplicity, Object has attributes: objectNumber and objectName.
If I were to create an instance of Object called instance, it would be held by ObjectCreator. Now let's say I needed another thread (let's call it ObjectChanger) to be able to see and manipulate instance; does it make sense to turn instance into a static Object?
I've managed to see results by making instance static so now I can do something like:
ObjectCreator.instance.getName();
Where getName() is a method of Object. From what I've read from answers to similar questions, static things are evil and there's always workarounds. One suggestion I've read is to pass instance to ObjectChanger as an argument for its constructor but what if instance wasn't created yet at the time I need to create an ObjectChanger?
Perhaps this question is more about OOP concepts than multi-threading or it may be a duplicate so forgive me but I'm quite lost here.
EDIT: To address frankie's and Jim's suggestions, here are some code snippets:
Object:
class Object
{
private String objectName = "Something";
private int objectNumber = 1;
public synchronized void changeNumber(int newNumber)
{
objectNumber = newNumber;
}
}
ObjectCreator:
class ObjectCreator extends Thread
{
static Object instance;
public ObjectCreator (Object something)
{
instance = something;
}
static void createObject()
{
...
}
static Object getObject()
{
return instance;
}
}
ObjectChanger:
public class ObjectChanger extends Thread
{
private Object currentInstance = null;
private int instanceNumber = null;
public void run()
{
currentInstance = ObjectCreator.getObject(); //If I were to make getObject() non-static, this line churns up an error
instanceNumber = currentInstance.getObjectNumber();
currentInstance.changeNumber(2); //valid?
}
}
If you want a thread to obtain access to an object not created within it, you must ensure that said thread has a path of references which it can follow, leading to the new object.
Consider the following code, with no threads involved.
class MyObject { /* ... */ }
interface MyObjectProvider {
MyObject getMyObject();
}
class Creator implements MyObjectProvider {
private MyObject obj;
/* ... */
#Override
public MyObject getMyObject() {
return obj;
}
/** Invoked at some point in time. */
void createMyObject() {
obj = new MyObject();
}
}
class Consumer {
private MyObjectProvider provider;
Consumer(MyObjectProvider mop) {
provider = mop;
}
void consume() {
// At some point in time...
MyObject o = provider.getMyObject();
}
}
Example of a program:
public static void main(String[] args) {
Creator creator = new Creator();
Consumer consumer = new Consumer(creator);
creator.createMyObject();
consumer.consume();
}
When you add threads to the mix, some code has to change, but the struture is the same.
The idea is to run the Creator in a thread, and the Consumer in another, as you've pointed out.
So, in short, these are the things you should be looking into:
Concurrency control: look into data races, synchronized, mutual exclusion, and their friends. Start here.
wait and notify, if the Consumer should wait for MyObject to be created. Look here.
When you have a nice grasp on these concepts, you may look into the volatile keyword (watch out for its pitfalls), and the java.util.concurrent package which provides better concurrency primitives, concurrent collections, and atomic variables.
You can put your objects in a list structure like Vector and store them in the ObjectCreator. Add a getter method to ObjectCreator which will accept an index of the object to be received.
This is just a skeleton showing the basic structure. Error handling is left as an exercise :-)
public class MyObject { ... }
...
public class MyObjectCreator {
private Map<String,MyObject> createdObjects = new HashMap<>();
public MyObject makeNewObject(int objNum, String objName)
{
MyObject o = new MyObject(objNum, objName);
this.createdObjects.put(objName,o);
}
public MyObject getObject(String objName)
{
return this.createdObjects.get(objName);
}
}
...
public class MyProgram {
public static void main(String[] args)
{
MyObjectCreator oc = new MyObjectCreator();
MyObject mo = oc.makeNewObject(10,"aNewObject");
...
MyObject o = oc.get("aNewObject");
...
If you only want to change the values of the fields of your class, you should just pass the object into your newly created thread. Then there is really no need to keep a static reference around in a holder class.
But as commented already, we need a bit more information to get to what you want to do with your object and thread.
Why cant you just make an getter in the ObjectCreator class that retrieves said Object?
ex: ObjectCreater.getMyObject()
EDIT:
I think you're looking for something like this if Im not mistaken:
public class ObjectCreator{
ArrayList<Object> children;
public ObjectCreator(){
children = new ArrayList<Object>();
}
//returns back index in children array (for accessing from other threads)
public int createObject( whatever params here ){
Object o = new Object( params );
children.add(o);
return children.size()-1;
}
}
since I dont know much about the problem you're trying to solve, Im not sure if it has to be thread safe, if you want these objects mapped, or accessed differently, but Im confused where all the confusion about static is coming...

Best way to implement the Factory Pattern in Java

I am trying to write a Factory Pattern to create either a MainMode or a TestMode in my program. The code I was previously using to create these objects was:
play = (isMode) ? new MainMode(numberRanges, numberOfGuesses) :
new TestMode(numberRanges, numberOfGuesses, randNo());
My Game (play) would either create a MainMode object or a TestMode object depending on a boolean value (isMode). As you can see I am adding an extra value into my TestMode object (randNo()). This value is used within TestMode to allow the user to input their own "Random Number", whereas within the MainMode constructor this was randomly generated. In this program both MainMode and TestMode are sub-classes of the abstract class Game.
Now I want to replace this line with a Factory Pattern, although I am unsure as my TestMode constructor requires an extra object and I am unsure where I would need to pass this value. If I were going to create a Factory it'd need to be in a new class, probably named GameFactory or ModeFactory or something along those lines.
How would I go about this?
EDIT: The problem here is that the code above is in my GUI, where the values for numberRanges, numberOfGuesses and the randNo() method are. I want to create a Factory class but I am unable to pass these values through because randNo() activates itself. Here is my randNo() method.
private int randNo() {
boolean isValidNumber = true;
int testRandomNum = 0;
while(isValidNumber) {
try {
testRandomNum = Integer.parseInt(JOptionPane.showInputDialog("Enter Random Number"));
isValidNumber = false;
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(null, "Sorry, but the number you entered was invalid");
}
}
return testRandomNum;
}
The problem is that whenever I pass randNo() it displays the JOptionPane. As I've said already the GUI and Logic is separate. The GUI is in a GUI package whilst the rest of the code is in the logic package.
Note that some of the other answers may arguably describe factories, but don't describe the GOF Factory Pattern.
Now I want to replace this line with a
Factory Pattern, although I am unsure
as my TestMode constructor requires an
extra object and I am unsure where I
would need to pass this value.
Well, you could think of it this way: MainMode, not TestMode, is the one that does a special thing. The special thing it does, is to ignore the given number, in order to ensure it's really random. In this way of thinking about it, it's MainMode that does something extra.
Or, if other than the randomness, MainMode and TestMode are not different, then you'd be thinking perhaps that you can factor out that similarity into one class, which is provided one of two Strategies for calculating random numbers. One Strategy would actually be random, and one would be perverse, with a random range of only 1 value.
But let's assume that there are other differences between MainMode and TestMode -- presumably TestMode outputs extra debugging to System.out or something.
We can still factor out "how do we supply randomness" from are we testing or playing the game for real". These are orthogonal concerns.
So now we know that in addition to whatever else a 'Mode does, it should accept a Randomness Strategy. Then we could, for example, when you're told that the standard platform random isn't really random enough, you can replace it with a better random.
Or you can do testing where the range of randoms is constrained to only two choices, or always alternates from one to zero, or returns on each call the next value in some Vecrtor or Iterator.
So we use the GOF Strategy Pattern to build the randomness strategies:
interface RandomStrategy {
public double random();
}
public class NotSoRandom implements RandomStrategy {
private double r;
public NotSoRandom( final double r ) { this.r = r; }
public double random() { return r; }
}
public class PlatformRandom implements RandomStrategy {
public double random() { return Math.random(); }
}
Now, if your whole app only ever creates one 'Mode, there's no need for a factory; you use a factory when you need to create the same class type over and over; the Factory is in fact just a Strategy for creating the right kind of (sub) class.
In production code, I've used factories where I have some generic class that creates stuff, and I need to tell how to create the right subclass to create; I pass in a factory to do that.
Now we create a Factory pattern for the 'Mode; this will be surprisingly similar to the Strategy pattern:
abstract class Mode() {
private RandomStrategy r;
public Mode( final RandomStrategy r ) { this.r = r; }
// ... all the methods a Mode has
}
public class MainMode implements Mode {
public MainMode( final RandomStrategy r ) { super(r); }
}
public class TestMode implements Mode {
public TestMode( final RandomStrategy r ) { super(r); }
}
interface ModeFactory{
public Mode createMode( final RandomStrategy r );
}
public class MainFactory() {
public Mode createMode( final RandomStrategy r ) {
return new MainMode(r);
}
}
public class TestFactory() {
public Mode createMode( final RandomStrategy r ) {
return new TestMode(r);
}
}
So now you know about the Factory Pattern and Strategy Pattern, and how they're similar in "shape", but different in how they're used: Factory Pattern is Object Creational and returns an object to be used; Strategy is Object Behavioral, and an instance is usually created explicitly and a reference is held to the instance, to encapsulate an algorithm. But in terms of the structure, they're quite similar.
Edit: the OP asks, in a comment, "How would I integrate this into my GUI?"
Well, none of this belongs in the GUI of your program, except possibly the 'Mode. You'd create the ConcreteStrategy and pass it to the preferred Factory in some setup routine, possibly determining which to use based on command line arguments or config files. basically, you'd select the correct factory very much as you selecting the correct class in your original post. Again, if you're only ever creating one of something, you don't need a Factory; factories are for mass production (or creating families of related concrete types -- though that's beyond the scope of this question).
(Assume we have a game where the user can select on the command line whether to fight robots or dragons; then we'd want to instantiate an OpponentFactory that produce Opponents (an interface), with derived classes RobotOpponent and DragonOpponent, and pass that factory to the part of the game that spawnsNewOpponent(). Similarly, a user might select brave or cowardly opponents, which we'd set up as a Strategy. We don't need to make more Strategy instances, as a Strategy is usually idempotent (stateless and singleton).)
static int main( String[] args ) {
// setup game world
final RandomStrategy r = "random".equals(args[0])
? new PlatformRandom() : new NotSoRandom( Integer.intValue(args[0]) ) ;
// notice the simlarity to the code you originally posted;
// we factored out how to achieve "randomness" as a Strategy.
// now we will use our Strategy to setup our Factory;
final ModeFactory f = "test".equals(args[1])
? new TestFactory(r) : new MainFactory(r);
// also similar to your code
// we've just added an extra level of indirection:
// instead of creating a Mode, we've created an object that can create Modes
// of the right derived type, on demand.
// call something that uses our factory
functionThatRunsameAndNeedstoProduceModesWhenevertNeedsTo( f );
}
The whole point of a Factory is that it should have the needed state to create your Game appropriately.
So I would build a factory like this:
public class GameFactory {
private boolean testMode;
public GameFactory(boolean testMode) {
this.testMode = testMode;
}
public Game getGame(int numberRanges, int numberOfGuesses) {
return (testMode) ? new MainMode(numberRanges, numberOfGuesses) :
new TestMode(numberRanges, numberOfGuesses, getRandom());
}
private int getRandom() {
. . . // GUI code here
}
}
Now you can initialize this factory somwhere in your app, and pass it in to whatever code needs to create a Game. This code now doesn't need to worry about what mode it is, and passing extra random params - it uses a well known interface to create Games. All the needed state is internalized by the GameFactory object.
Try somthing like,
abstract class ModeFactory {
public static Mode getMode(isMode, numberRanges, numberofGuesses) {
return isMode ? new MainMode(numberRanges, numberofGuesses) : new TestMode(numberRanges, numberOfGuesses, randNo());
}
public static Mode getMode(isMode, numberRanges, numberofGuesses, someNumber) {
return isMode ? new MainMode(numberRanges, numberofGuesses) : new TestMode(numberRanges, numberOfGuesses, someNumber);
}
}
The class is abstract just to stop intialization. You could modify it to use final and then create a private constructor.
Your code could probably be changed into a factory pattern.
Something like:
public static Mode createMode(boolean isMainMode)
{
if(isMainMode) return new MainMode(...);
return new TestMode(...);
}
Place this method somewhere sensible (this one is tricky, maybe a static ModeFactory)
This assumes that MainMode and TestMode are subtypes of the same type (subclasses or implement Mode interface)
Now all play has to do is call ModeFactory.createMode(...) and pass the appropriate boolean.
Edit (in response to OP update):
Your rand() gets evaluated before the actual constructor is called, and it presents the GUI. Is that what you mean by activating itself?
You have to make the design decision where you want to make the decision about the mode. If you have a GUI and you have a model, it might be preferable to design the GUI to know whether or not the call to random generation (and popup) is necessary before you call the factory method, and then pass the random number to the factory method and let it just pick the correct constructor.
Having it the other way around (model calls your GUI) is trickier and probably a bad idea.
interface ModeFactory {
Mode createMode(int numberRanges, int numberOfGuesses);
}
class MainModeFactory implements ModeFactory {
Mode createMode(int numberRanges, int numberOfGuesses) {
return new MainMode(numberRanges, numberOfGuesses);
}
}
class TestModeFactory implements ModeFactory {
Mode createMode(int numberRanges, int numberOfGuesses) {
return new TestMode(numberRanges, numberOfGuesses, randNo());
}
}
...
play = modeFactory.createMode(numberRanges, numberOfGuesses);
So at startup you create the appropriate mode factory, passing it in to wherever the play needs to be created.
Very simply, ALWAYS USE A PARAMETER, in case the parameter is not used, send null, if you have several parameters for other "Modes", encapsulate them, into a single parameter.
If you are just after factory method, that will create for you a class of a given name try this:
public static MyInterface createClass(String name) throws IllegalAccessException,
InstantiationException, ClassNotFoundException {
try {
Class myClass = Class.forName(name);
MyInterface myObj = (MyInterface) myObj.newInstance();
return myObj;
} catch (ClassNotFoundException ex) {
logger.error("Could not find a class {}", name);
throw ex;
} catch (InstantiationException e) {
logger.error("Class must be concrete {}", name);
throw e;
} catch (IllegalAccessException e) {
logger.error("Class must have a no-arg constructor {}", name);
throw e;
}
}
What you realy want to do, is make a factory, which returns you an object of abstract class or interface (theyr implementors of course). In the factory method you then deside, which implementor to choose. You if you choose an abstract class, you can implement some common logic in it and let other methods unimplemented (declaring them abstract). You would let the concrete descenders implement them depending on theyr need. This is factory design pattern:
public class GridManagerFactory {
public static AbstractGridManager getGridManager(LifecicleAlgorithmIntrface lifecicleAlgorithm, String... args){
AbstractGridManager manager = null;
// input from the command line
if(args.length == 2){
CommandLineGridManager clManager = new CommandLineGridManager();
clManager.setWidth(Integer.parseInt(args[0]));
clManager.setHeight(Integer.parseInt(args[1]));
// possibly more configuration logic
...
manager = clManager;
}
// input from the file
else if(args.length == 1){
FileInputGridManager fiManager = new FileInputGridManager();
fiManager.setFilePath(args[0]);
// possibly more method calls from abstract class
...
manager = fiManager ;
}
//... more possible concrete implementors
else{
manager = new CommandLineGridManager();
}
manager.setLifecicleAlgorithm(lifecicleAlgorithm);
return manager;
}
}
The commoun logic in the abstract class is available to its descenders:
public abstract class AbstractGridManager {
private LifecicleAlgorithmIntrface lifecicleAlgorithm;
// ... more private fields
//Method implemented in concrete Manager implementors
abstract public Grid initGrid();
//Methods common to all implementors
public Grid calculateNextLifecicle(Grid grid){
return this.getLifecicleAlgorithm().calculateNextLifecicle(grid);
}
public LifecicleAlgorithmIntrface getLifecicleAlgorithm() {
return lifecicleAlgorithm;
}
public void setLifecicleAlgorithm(LifecicleAlgorithmIntrface lifecicleAlgorithm) {
this.lifecicleAlgorithm = lifecicleAlgorithm;
}
// ... more common logic and geter-seter pairs
}
The concrete implementor only need implement the method which is declared abstract:
public class FileInputGridManager extends AbstractGridManager {
private String filePath;
#Override
public Grid initGrid() {
return this.initGrid(this.getFilePath());
}
public Grid initGrid(String filePath) {
List<Cell> cells = new ArrayList<>();
char[] chars;
File file = new File(filePath); // for ex foo.txt
// ... more logic
return grid;
}
}
The receiver of AbstractGridManager would call the methods on him and get the logic, implemented in the concrete descenders (and partually in the abstract class methods) without knowing what is the concrete implementation he got. This is also know like inversion of control or dependency injection

Categories

Resources