Java-Gaming.org    
Featured games (79)
games approved by the League of Dukes
Games in Showcase (477)
Games in Android Showcase (107)
games submitted by our members
Games in WIP (535)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Trying to get my head around the factory design pattern  (Read 805 times)
0 Members and 1 Guest are viewing this topic.
Offline niroshido

Junior Member


Medals: 4
Exp: 4 years



« Posted 2014-01-22 01:35:30 »

Hey again, so yeah i have been messing about trying to figure out the practicalities of the factory design pattern in java.
before i show you my code let me try to explain what i am trying to do. I am trying to create some functionality that will allow you to create any type of entity (lets say you wanted to build infantry as opposed to tanks) you wish on runtime and also allow me to extend on what types of entities i want to allow be created without having to mess around. So anyways here is what i have.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
//this is actually the factory for creating entities.
package com.niroshido.gameObjects;

public class EntityFactory {
   
   public Entity create(String name){
      switch(name.toLowerCase()){
      case "aircraft": Entity air = new Aircraft();
      return air;
      case "tank": Entity tank = new Tank();
      return tank;
      default: return null;
      }      
   }
}

1  
2  
3  
4  
5  
6  
7  
//yup this interface doesn't do anything, i had spent a while trying to figure out
//what if anything should be inside this interface, but i draw a blank.
package com.niroshido.gameObjects;

public interface Entity {
   
}

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
//this is a super class that most entites would inherit from, the exception being things that can't move/attack like //buildings
package com.niroshido.gameObjects;

public class Units implements Entity{

   private int healthPoints;
   private int attackDamage;
   private int speed;
   private int rotationSpeed;

   public void move(){
     
   }
   
   public void drawUnit(){
     
   }
   
   public void attack(Entity e, Entity target){
     
   }
   
   public int getHealthPoints() {
      return healthPoints;
   }
   
   public void setHealthPoints(int healthPoints) {
      this.healthPoints = healthPoints;
   }
   
   public int getAttackDamage() {
      return attackDamage;
   }
   
   public void setAttackDamage(int attackDamage) {
      this.attackDamage = attackDamage;
   }
   
   public int getSpeed() {
      return speed;
   }
   
   public void setSpeed(int speed) {
      this.speed = speed;
   }
   
   public int getRotationSpeed() {
      return rotationSpeed;
   }
   
   public void setRotationSpeed(int rotationSpeed) {
      this.rotationSpeed = rotationSpeed;
   }  
}


1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
//this is rather obvious, its a subclass, a specific type of unit.
package com.niroshido.gameObjects;

public class Tank extends Units{
   
   public Tank(){
      System.out.println("tank");
      this.setHealthPoints(200);
      System.out.println(this.getHealthPoints());
   }
   
   public void move(){
     
   }
}


in my mind this is how i see my code as is
factory <- Creates- Entity <-implements- Units<-extends- Tank

now my main issue really comes down to, moving, drawing, attacking etc. In my factory class i decided to try and see if i could call a method from Tank, i can't it wont allow me, i assume that this is actually logical and expected after all the factory design pattern is supposed to abstract the creation process and simply stop people from screwing around with the actual sub class of Units directly, am i right with this?. If this is the case what would the point of me having move or any of those methods in Units if i can't access them as a result (at this point i clearly need to guidance), should i not have those methods there and simply create a different class for processing orders (attack, move, defend) that take a type of Entity as a parameter, I am sure there is a lot of people here who could understand what i am trying to achieve, possibly.

to describe this is a nut shell, i obsess about good code design, if i feel that if its not designed to the point it shines like a lighthouse at night i have failed miserably.
Offline HeroesGraveDev

JGO Kernel


Medals: 238
Projects: 11
Exp: 2 years


┬─┬ノ(ಠ_ಠノ)(╯°□°)╯︵ ┻━┻


« Reply #1 - Posted 2014-01-22 02:02:50 »

The factory pattern is for initialising classes with lots of variables to be set, but where some may be fine just left as the defaults.

The point is you create a factory, and then set the options you want to change from the defaults, and then call a finish function to get the final object.
1  
2  
3  
4  
5  
6  
SomeFactory factory = new SomeFactory();

factory.setSomeInt(5);
factory.setSomeString("This statement is false");

SomeObject object = factory.getResult();


Where factory may have lots more functions available than the ones you called.

Once the object has been fully initialised, you should not be using the factory anymore.

Edit: Disregard the above. I mixed up the Factory and Builder patterns.

More on design patterns:

Never do something because the code looks nice.
Do something because it's the most efficient way of doing it.
Your end-user will care more about you getting the project done faster than being told "the code looks nicer".
Fortunately, efficient coding usually looks nice.

Offline jays

Junior Newbie





« Reply #2 - Posted 2014-01-22 05:58:42 »

note: im no guru and this is probably not my place to say

but as for your entity system

the whole point of an entity system is to be able to dynamically control more then one character i.e. tank, soldier, plane so you dont have to have separate interaction functions for each character (polymorphic)

just wanted to say that after seeing your empty entity interface (not sure if was example orrr....)

also in this case your entity interface is pointless and unit should be renamed to entity

as for your main question

id just have a controller class storing all your entities with the same concept of the "entity" system itself
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline HeroesGraveDev

JGO Kernel


Medals: 238
Projects: 11
Exp: 2 years


┬─┬ノ(ಠ_ಠノ)(╯°□°)╯︵ ┻━┻


« Reply #3 - Posted 2014-01-22 06:12:48 »

also in this case your entity interface is pointless and unit should be renamed to entity

What about non-unit entities?

Offline jays

Junior Newbie





« Reply #4 - Posted 2014-01-22 07:30:17 »

also in this case your entity interface is pointless and unit should be renamed to entity

What about non-unit entities?

i was only speaking in terms of this case
Offline Danny02
« Reply #5 - Posted 2014-01-22 08:35:33 »

The factory pattern is for initialising classes with lots of variables to be set, but where some may be fine just left as the defaults.

The point is you create a factory, and then set the options you want to change from the defaults, and then call a finish function to get the final object.

Nope, thats the Builder-Pattern Wink
Offline HeroesGraveDev

JGO Kernel


Medals: 238
Projects: 11
Exp: 2 years


┬─┬ノ(ಠ_ಠノ)(╯°□°)╯︵ ┻━┻


« Reply #6 - Posted 2014-01-22 08:41:08 »

Yes it is. I mixed them up. Cranky

Offline niroshido

Junior Member


Medals: 4
Exp: 4 years



« Reply #7 - Posted 2014-01-22 13:21:16 »

hi everyone, thanks for the replies, i think i need to go into more detail about what i am trying to achieve.
I like RPG's and RTS games, my idea was to eventually piece together an RTS. my entity based system was designed to include stuff that typically cannot be interacted with by the player as well as those that can, it is supposed to encompass all types of object, i wanted to keep it abstract enough so that i could simply just add a new class to define a new type of entity when i come up with an idea.

i chose the factory pattern because my understanding is the factory pattern abstracts what is being instantiated. An entity can be anything within the game world, it can be a treasure chest or it could be a soldier, it may be passable it may not.
Offline Troubleshoots

JGO Knight


Medals: 36
Exp: 7-9 months


Damn maths.


« Reply #8 - Posted 2014-01-22 16:50:03 »

I'll start off by commenting on your code, and explaining its flaws.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
public class EntityFactory {
   
   public Entity create(String name){
      switch(name.toLowerCase()){
      case "aircraft": Entity air = new Aircraft();
      return air;
      case "tank": Entity tank = new Tank();
      return tank;
      default: return null;
      }      
   }
}

This has a couple of issues:
  • Returns null if the wrong string is passed in, i.e it's not type-safe.
  • Requires an instance of the class to create an entity.

Fixing those issues would result in this:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
public class EntityFactory {

   public enum EntityType {
      AIRCRAFT, TANK;
   }
   
   public static Entity create(EntityType type) {
      switch(type) {
      case AIRCRAFT:
         return new Aircraft();
         break;
      case TANK:
         return new Tank();
         break;
      }      
   }
}

This ensures type safety meaning that all errors are picked up at compile time, however it doesn't go far enough. You have both an enum and a class, however the class only has one static method in it. You could simply move the static method to the enum, which would result in this:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
public enum EntityType {
   AIRCRAFT, TANK;
   
   public static Entity create(EntityType type) {
      switch(type) {
      case AIRCRAFT:
         return new Aircraft();
         break;
      case TANK:
         return new Tank();
         break;
      }      
   }
}

Another way to do it would to be to get rid of the static method altogether and replace it with an abstract method in the enum. This would look like:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
public enum EntityType {
   AIRCRAFT {
      @Override
      public Entity create() {
         return new Aircraft();
      }
   },
   TANK {
      @Override
      public Entity create() {
         return new Tank();
      }
   };
   
   public abstract Entity create();
}

And you could create an entity by simply calling
Entity aircraft = EntityType.AIRCRAFT.create()
. However all of this seems unnecessary, which it is.

Your main issue is that you're not using Unit as the base class. Think about it this way, if entity is a unit, why do you inherit the behaviours and states of an entity as a unit? Instead, you should be inheriting the behaviours and states of a unit as an entity. If you had another class, for example Building, then inheriting the behaviours and states for an entity and for a building would mean that every unit would be both a building and an entity. Inheriting the behaviours and states for a unit as a building and as an entity would mean that a building is a unit and that an entity is a unit. Everything has an is a relationship.

  • Entity is a unit
  • Building is a unit
  • Aircraft is an entity
  • Tank is an entity
  • House is a building
  • Tower is a building

This means that Aircraft should inherit the behaviours and states of Entity and that Entity should inherit the behaviours and states of Unit. Similarly, Tower should inherit the behaviours and states of Building and Building should inherit the behaviours and states of Unit. Forget about using interfaces; only use an interface for an behaves like a relationship. Instead, use abstract  classes. Interfaces allow you to inherit the types of behaviours of an object, and to specify how the object acts out those behaviours. Abstract classes allow you to inherit an objects states, an objects pre-specified behaviours and allows you to abstract certain behaviours in the same way as an interface.

So if every unit has health, you would create an abstract unit class and specify health as a state.
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
public abstract class Unit {

   protected int health;

   protected Unit(int health) {
      this.health = health;
   }
 
   // note that it's package-private, only allows other units to set health
  void applyDamage(int damage) {
      health -= damage;
      if (health <= 0) {
         destruct();
      }
   }

   public int getHealth() {
      return health;
   }

   abstract void destruct(); // each unit might destruct in a different way

}

If every Entity is a unit and can attack other units, however the way in which each unit attacks other units is different, you would create an abstract Entity class that abstracts how the entity attacks another unit.
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
public abstract class Entity extends Unit {

   protected int speed;
   protected int damage;

   protected Entity(int attackSpeed, int attackDamage, int health) {
      super(health);
      this.speed = attackSpeed;
      this.damage = attackDamage;
   }

   public abstract void attack(Unit unit);

   public abstract void destruct();

}


And for each entity you would abstract the attack method, e.g:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
public class Aircraft extends Unit {

   public Aircraft(int attackSpeed, int attackDamage, int health) {
      super(attackSpeed, attackDamage, health);
   }

   public void attack(Unit unit) {
      unit.applyDamage(damage); // apply damage at a certain rate, do whatever... you can do some fancy stuff
  }

   public void destruct() {
      // do some animation, maybe fall to ground and explode? apply damage from this for example?
  }

}


So yeah, designing it in this way allows you to specify the behaviours you want to inherit and how you want to inherit them. To create an Aircraft for example, you can just do
Unit aircraft = new Aircraft(20, 2, 100)
. It's much better than your old approach. Oh, and just to note that if every entity for example attacked other units in the same way, then you could just specify the behaviour of attacking other units in the entity class and you wouldn't need to abstract it.

Why are all OpenGL tutorials written in Brainf**k?
Offline niroshido

Junior Member


Medals: 4
Exp: 4 years



« Reply #9 - Posted 2014-01-23 20:29:36 »

Thats a very detailed response Troubleshoots, thank you. I will have to re-read the reply so i can fully absorb what you are explaining but i certainly appreciate it
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline seismic

Senior Member


Medals: 4
Projects: 1



« Reply #10 - Posted 2014-01-23 20:56:46 »

Hmm nice read. Bookmarked :p
Edit: I guess you could put those abstract methods into an interface to further clean up your base class for example.

Also this is a good read to learn about the difference between abstract classes and interfaces
http://obviam.net/index.php/design-in-game-entities-object-composition-strategies-part-1/
Offline stefoid

Junior Newbie





« Reply #11 - Posted 2014-01-29 05:50:38 »

Ive never written a factory class in my life, but the internet tells me that you use a factory pattern when you want to delegate the business of creating something form the code that uses it. 

Like - i want to use an iPad, but I don't want to have to build one.  I don't know how to build one - so I delegate that to Apple.

This is a separate issue to what you are concerned with, which is ( I believe) that all your entities have a common interface?

www.armpitgames.com ARMPIT GAMES game design blog
www.dungeonbash.com Dungeon Bash
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

pw (37 views)
2014-07-24 01:59:36

Riven (38 views)
2014-07-23 21:16:32

Riven (26 views)
2014-07-23 21:07:15

Riven (28 views)
2014-07-23 20:56:16

ctomni231 (59 views)
2014-07-18 06:55:21

Zero Volt (50 views)
2014-07-17 23:47:54

danieldean (42 views)
2014-07-17 23:41:23

MustardPeter (44 views)
2014-07-16 23:30:00

Cero (60 views)
2014-07-16 00:42:17

Riven (57 views)
2014-07-14 18:02:53
HotSpot Options
by dleskov
2014-07-08 03:59:08

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:58:24

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:47:22

How do I start Java Game Development?
by ra4king
2014-05-17 11:13:37

HotSpot Options
by Roquen
2014-05-15 09:59:54

HotSpot Options
by Roquen
2014-05-06 15:03:10

Escape Analysis
by Roquen
2014-04-29 22:16:43

Experimental Toys
by Roquen
2014-04-28 13:24:22
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!