Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: The 'new' keyword, factory patterns  (Read 5115 times)

0 Members and 1 Guest are viewing this topic.

Walker

  • Full Member
  • ***
  • Posts: 181
    • View Profile
The 'new' keyword, factory patterns
« on: January 23, 2010, 05:07:28 pm »
I am trying to learn about object creation and factory patterns. I understand that you have a class that contains functions to create new objects and I would hope it tracks the individual objects somehow.

Does the factory pattern take care of keeping track of the objects? Do you use the new keyword to do the actual creation? I have never used this keyword before. I would like to see an example in C++ and any other tips you may have would be greatly apprectiated.

Cheers

gsaurus

  • Sr. Member
  • ****
  • Posts: 262
    • View Profile
    • Evolution Engine
The 'new' keyword, factory patterns
« Reply #1 on: January 24, 2010, 12:21:43 am »
I never read or seen an example to guide myself and decided to do it by myself.

On my project's prototype I had a static class responsible for the game data storage, with tables about the objects already loaded. I was referring to them by their filename, a string. Maybe not the best option, but worked fine for a first try. Each time I needed to create a new object (that can even be composed of several objects), I call a static method requesting for that object, like getCharacter(fileName),  getAnimation(filename), etc. it looks at the table, if exists, return, if not, load it from file, and all of it's components. This dynamic approach can be bad if I need an object in real time on the middle of the game, it's loading time can ruin the game. However I always load them some time before I need them, like at start of level or perhaps in a thread some seconds before I need it (on the proto I just load them all at start of scene)

If I wish I could add a counter for the number of times an object was called, so I can manage memory when objects are released like a garbage collector. But sometimes it is better to keep some objects in memory even if we aren't using them for a while.

I think I'll go with something like this on my next implementation, with some improvements, maybe looking forward on the scene to know what objects can be actually released or not. But I also considere search a bit to see how factories are usually implemented. Though I think it always depends on the game and it's needs
Pluma - Plug-in Management Framework

dogmaan

  • Newbie
  • *
  • Posts: 6
    • View Profile
The 'new' keyword, factory patterns
« Reply #2 on: January 24, 2010, 03:16:48 am »
this is how i do it

Code: [Select]


void scenemanager::addObj_lua (string lab, int X, int Y, string ty)
{
    // if object doesn't exist
if (entityMap.find(ty) == entityMap.end())  
{
//create new master entity
entity * Entity = new entity (*this, App, luaVm, entityFileList[ty], ty, X, Y);
entityMap[ty] = Entity;
entityList.push_back(Entity);
cout << "testing addobj " << entityFileList[ty] << endl;
    }

        else
{
// create a copy of the entity
entityMap[ty]->createEntityCopy(X, Y);
}


}

void entity::createEntityCopy(int X, int Y)
{
if(player)
{
baseEntity * newPlayer = new playerEntity(X, Y, *this);
derivedEntities.push_back (newPlayer);
newPlayer->init();
   }
   else
   if (staticEntity)
   // create a static entity
   etc etc
   
}





each master entity has access to the LuaVm which it pulls it's variables from

Walker

  • Full Member
  • ***
  • Posts: 181
    • View Profile
The 'new' keyword, factory patterns
« Reply #3 on: January 24, 2010, 06:30:24 am »
I'm starting to get the basics of this now, thanks for the code example. But I am still missing how to actually keep track of each object that is created.

I'm not sure how to ask my question so I will provide an example.

I want to make a simple program to test the factory pattern. You will be able to left click on the window to spawn an object at the cursor and a right click will delete the object or even allow you to drag it around. Preferably there should be no limit on the number of objects that exist at once (I guess using an STL container comes into this).

I think I understand the creation part, but I don't know how to get from mouse coordinates (or any input) to telling which instance should be edited or deleted.

gsaurus

  • Sr. Member
  • ****
  • Posts: 262
    • View Profile
    • Evolution Engine
The 'new' keyword, factory patterns
« Reply #4 on: January 24, 2010, 02:47:07 pm »
I consider that the factory keeps raw material (like sf::Image) and produces objects based on that raw material (like sf::Sprite).
Other classes are clients of the factory. Like a Scene class, it stores and uses light objects like sf::Sprite.
That way you have multiple light objects on a higgher class, using the same heavy data that is stored on the factory.

The factory is responsible for creating and provide the light objects, but not to store them. The client stores and manipulates light objects, but don't care on how it was built, and what and where is the low level and hard data of it. Just like in real life!
This is how I see it :wink:

Let's for example consider that factory takes care of sf::Images and Scene takes care of sf::sprites.

To simplify, load all images you need on the factory at start of the application, and free them at application termination.
Example:
Code: [Select]

Factory::loadEverything();
while(App.IsOpened()){
    ...
}
Factory::clearEverything();


On your example, your Scene class has a Sprite for each object in the scene. The sprites can be stored in some container.
When left click on screen, the Scene requests the factory for a new sprite of certain type. The factory creates a sprite using a specific image that is defined by the type (case type_tree: sprite->SetImage(tree_image) for example) Finally return it to the Scene, which stores it on the container.
Code: [Select]
someContainer.push_back( Factory::CreateTree(mouseX, mouseY) );
or
Code: [Select]
someContainer.push_back( Factory::CreateObject(ObjTypes::tree, mouseX, mouseY) );

When you right click, you search on the container for a sprite that intersects the mouse coordinates (test if it's inside a bounding box for example). Once you find it, just remove it from the container.


It becomes more useful when managing animations and other more complex raw data  :wink:

This was a simple example, you may want to specify what happens when you request an object which the raw data needed for it doesn't exist on the factory yet. You can load it or just raise an error. Or you can keep track of how many objects are using a certain raw data, when they are removed on the Scene, notify the factory so that when the last light object using a certain data is removed, the factory can delete the data, etc.
Pluma - Plug-in Management Framework

Walker

  • Full Member
  • ***
  • Posts: 181
    • View Profile
The 'new' keyword, factory patterns
« Reply #5 on: January 25, 2010, 05:02:15 am »
Okay, I think the only bit now that I am unsure of is what sort of container to use to store objects and perhaps the actual create object function in the factory. Does the function return the object?

Code: [Select]
return new Pizza(X, Y);

or

Code: [Select]
object = new Pizza(X, Y);
return object;


What is the correct way to use the 'new' keyword?

EDIT: Okay, I managed to create a new object using a function, and add it to an STL vector, now my question is how do I access one of my stored objects?

dogmaan

  • Newbie
  • *
  • Posts: 6
    • View Profile
The 'new' keyword, factory patterns
« Reply #6 on: January 25, 2010, 07:57:01 pm »
Quote from: "Walker"
Okay, I think the only bit now that I am unsure of is what sort of container to use to store objects and perhaps the actual create object function in the factory. Does the function return the object?

Code: [Select]
return new Pizza(X, Y);

or

Code: [Select]
object = new Pizza(X, Y);
return object;


What is the correct way to use the 'new' keyword?

EDIT: Okay, I managed to create a new object using a function, and add it to an STL vector, now my question is how do I access one of my stored objects?



Code: [Select]

vector <object>      objectVec;
vector <object *>    objectPtrVec;



// if each of your pushed back objects have an update function you would access the first object like this

int i = 0;

// if it is an object
objectVec[i].update();

// if it is a pointer to an object
objectPtrVec[i]->update();

Walker

  • Full Member
  • ***
  • Posts: 181
    • View Profile
The 'new' keyword, factory patterns
« Reply #7 on: January 26, 2010, 06:57:54 am »
Thanks, that was the bit I needed. I just didn't expect it to be that simple.

Cheers

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
The 'new' keyword, factory patterns
« Reply #8 on: January 28, 2010, 02:17:30 pm »
When you use dynamic memory management, new is just one side. Never forget to free the memory with delete! Otherwise, you get memory leaks, and the available RAM will continuously shrink.

If the factory doesn't return encapsulated objects that are able to free the memory themselves (for example smart pointers like std::auto_ptr), there should be DestroyXYZ() functions in the factory interface, corresponding to CreateXYZ(). It is important not to write a delete directly in the client code (instead of a DestroyXYZ() call), destruction should be an implementation detail.

However, you don't mandatorily need the free store ("heap"). A factory can also return objects by value. Whether this approach is appropriate, depends on the circumstances. For example, for noncopyable classes, that's no option.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development: