I considered this scenario: objects that roughly look like this:
class PhyisicalObject
{
private:
virtual void Update() = 0;
friend class PhysicsController;
void DoUpdate() { this->Update(); }
};
There's a controller class called a PhysicsController that manages the dynamics of a pool of physical objects by calling their DoUpdate() method. This method, in terms, calls an overloaded version of the Update()function where a numerical integrator is used to compute the objects position, velocity and acceleration step-wise. I thought that having an interface implying this functionality would be a good starting point:
class IIntegrator
{
virtual void opertor() (const vec3& pos, const vec3& vel, vec3& outPos, vec3& outVel);
};
Now inheriting this IIntegrator abstract class and providing the implementation for various methods is the next step (explicit Euler, RK4, Verlet, Midpoint, Symplectic Euler and perhaps some semi-implicit/IMEX or implicit ones would be excellent). The problem is that I don't see clearly how to do the following two things:
Each physical object computes its own acceleration at any of its vertices in different ways (considering the objects consist of masspoints connected through springs or some kind of constraining objects). This function must be passed to the integrator, but it is object specific. It is possible to get pointers to non-static methods, but how would this fit the IIntegratorinterface?
When an object calls its Update() method, what happens behind the scenes is that an integrator is used to provide the functionality. I'd like to switch the integration method on the fly, perhaps. Or at least instantiate the same kind of object with different integrators. To me, it sounds like a factory doing that and, for on-the-fly integrator switching.. perhaps a strategy pattern? What solution would be quite elegant and efficient in this context?
Without going into implementation details, here are a few design patterns that might be applied to your problem
Factory or Prototype To create objects at startup from a file, or clone them during run-time, respectively.
Composite This might be used to model PhysicalObjects, either as stand-alone objects or collections connected by strings, springs or gravitational forces.
Iterator or Visitor This might be used by PhysicsController to iterate over all physical objects (composite or stand-alone) and apply a function over them.
Strategy To select different IIntegrator objects and their integration functions at runtime.
Apart from the GoF book (Amazon), a good online resource is here
Related
I have a class item. Each instance of this class is an object in 3D space, can be basic shapes like cylinder, sphere and cone. The class Item has a convenient API for geometry (radius, top radius, bot radius, length) and transformations (rotation, translation, scale).
enum ItemType {
Sphere = 1,
Cone
}
class Item
{
// ...
public:
ItemType type();
void setType(const ItemType &t);
float radius();
float length();
float topRadius();
float botRadious();
QMatrix4x4 transformations();
void setRadius(const float &r);
void setLength(const float &l);
void setTopRadius(const float &tr);
void setBotRadius(const float &br);
void setTransformations(const QMatrix4x4 &matrix);
// ...
}
Frequently, I want to glue multiple objects together to form a unified shape. For example, two spheres and a cone are connected below. The geometry and transformations of the unified object is dependent upon those of two spheres and one cone.
The problem is:
Convenient handling of the unified object is not possible
By handling, I mean, for example, transforming. Like changing the length of the unified object which requires, changing the length of the middle cone and location of the two spheres accordingly.
class Item has API for convenient handling of each individual object, but not the unified one
For handling of the unified object, I have to work with three different objects which is torturous
The question is:
Which design patterns are best suited to conveniently handle the unified objects?
Note: This question is about object oriented software design and software patterns, it has nothing to do specifically with C++. The only part that is C++ specific is the use of the virtual keyword, but even that, is just the C++-specific keyword that gives you polymorphism, which is again, an object-oriented principle, not something unique to C++.
So, what you first of all need to do, is to extract a true interface for what you call "API". I would call this Primitive3D, and it would be a class containing nothing but pure virtual methods. (In C++, that would be virtual function(parameters) = 0.)
Then, each one of your primitives would be implementing the interface by providing an implementation for each pure virtual method. If you have some basic functionality that all implementations will share, then in addition to implementing this interface you can also keep a common base class. However, the introduction of the interface will keep your options more open.
Then, introduce a new primitive, called perhaps Conglomerate. Again, that would be yet one more class implementing Primitive3D. That class would provide its own implementations for setting various attributes like length and transformation, and these implementations would work by setting some of the attributes of contained primitives.
The Conglomerate class would also provide a few functions which are specific to it and cannot be found in the Primitive3D interface. You would use these functions to configure the conglomerate, at the very least to populate the conglomerate with its contents.
The function which adds a new member primitive to the conglomerate may accept additional parameters to indicate precisely at which position of the conglomeration the new member should appear, what kind of transformation to perform when scaling the primitive, what kind of transformation to perform when translating the primitive, etc.
Internally, the conglomeration would probably make use of a vector containing instances of some internal member structure, which would contain a reference to a Primitive3D and any other information that is necessary so as to know how to handle that primitive. Do not make the mistake of adding this information to the Primitive3D itself, it does not belong there, because a primitive does not know, and should not know, that it is a member of a conglomeration. I would even go as far as to say that the location of a primitive is not a feature of the primitive itself; it is a feature of the space that contains the primitive, whether this space is the universe, or a conglomeration.
Looking at your structure, composite is the pattern you should consider. Also identifying concrete shape with 'type' attribute is against object oriented design. It kills polymorphism, a great unique tool available in OO. Composite pattern will allow you to address elements as well as their aggregation in one hiearchy.
In my simulation I have different objects that can be sensed in three ways: object can be seen and/or heard and/or smelled. For example, Animal can be seen, heard and smelled. And piece of Meat on the ground can be seen and smelled but not heard and Wall can only be seen. Then I have different sensors that gather this information - EyeSensor, EarSensor, NoseSensor.
Before state: brief version gist.github.com link
Before I started implementing NoseSensor I had all three functionality in one class that every object inherited - CanBeSensed because although classes were different they all needed the same getDistanceMethod() and if object implemented any CanBeSensed functionality it needed a senseMask - flags if object can be heard/seen/smelled and I didn't want to use virtual inheritance. I sacrificed having data members inside this class for smell, sounds, EyeInfo because objects that can only be seen do not need smell/sound info.
Objects then were registered in corresponding Sensor.
Now I've noticed that Smell and Sound sensors are the same and only differ in a single line inside a loop - one calls float getSound() and another float getSmell() on a CanBeSensed* object. When I create one of this two sensors I know what it needs to call, but I don't know how to choose that line without a condition and it's inside a tight loop and a virtual function.
So I've decided to make a single base class for these 3 functionality using virtual inheritance for base class with getDistanceMethod().
But now I had to make my SensorBase class a template class because of this method
virtual void sense(std::unordered_map<IdInt, CanBeSensed*>& objectsToSense) = 0;
, and it meant that I need to make SensorySubSystem class(manages sensors and objects in range) a template as well. And it meant that all my SubSystems like VisionSubSystem, HearingSubSystem and SmellSubSystem inherit from a template class, and it broke my SensorySystem class which was managing all SensorySubSystems through a vector of pointers to SensorySubSystem class std::vector<SensorySubSystem*> subSystems;
Please, could you suggest some solution for how to restructure this or how to make compiler decide at compile time(or at least decide once per call//once per object creation) what method to call inside Hearing/Smell Sensors.
Looking at your original design I have a few comments:
The class design in hierarchy.cpp looks quite ok to me.
Unless distance is something specific to sensory information getDistance() doesn't look like a method that belongs into this class. It could be moved either into a Vec2d-class or to a helper function (calculatePositon(vec2d, vec2d)). I do not see, why getDistance() is virtual, if it does something different than calculating the distance between the given position and the objects position, then it should be renamed.
The class CanBeSensed sounds more like a property and should probably be renamed to e.g. SensableObject.
Regarding your new approach:
Inheritance should primarily be used to express concepts (is-a-relations), not to share code. If you want to reuse an algorithm, consider writing an algorithm class or function (favour composition over inheritance).
In summary I propose to keep your original class design cleaning it up a little as described above. You could add virtual functions canBeSmelled/canBeHeard/canBeSeen to CanBeSensed.
Alternatively you could create a class hierachy:
class Object{ getPosition(); }
class ObjectWithSmell : virtual Object
class ObjectWithSound : virtual Object
...
But then you'd have to deal with virtual inheritance without any noticeable benefit.
The shared calculation code could go into an algorithmic class or function.
I have an collection of objects which represents a model of a system. Each of these objects derives from a base class which represents the abstract "component". I would like to be able to look at the system and choose certain behaviours based on what components are present and in what order.
For the sake of argument, let's call the base class Component and the actual components InputFilter, OutputFilter and Processor. Systems that we can deal with are ones with a Processor and one or both filters. The actual system has more types and more complex interaction between them, but I think this will do for now.
I can see two "simple" ways to handle this situation with a marshalComponentSettings() function which takes one of the collections and works out how to most efficiently set up each node. This may require modifying inputs in certain ways or splitting them up differently, so it's not quite as simple as just implementing a virtual handleSettings() function per component.
The first is to report a enumerated type from each class using a pure virtual function and use those to work out what to do, dynamic_cast'ing where needed to access component specific options.
enum CompType {
INPUT_FILTER,
OUTPUT_FILTER,
PROCESSOR
}
void marshal(Settings& stg)
{
if (comps[0].type() == INPUT_FILTER)
setUpInputFilter(stg); //maybe modified the stg, or provides other feedback of what was done
// something similar for outputs
setUpProcessor(stg);
}
The second is to dynamic_cast to anything that might be an option in this function and use the success of that or not (as well as maybe the cast object if needed) to determine what to do.
void marshal(Settings& stg)
{
if (InputFilter* filter = dynamic_cast<InputFilter*>(comp[0]))
setUpInputFilter(stg); //maybe modified the stg, or provides other feedback of what was done
// something similar for outputs
setUpProcessor(stg);
}
It seems that the first is the most efficient way (don't need to speculatively test each object to find out what it is), but even that doesn't quite seem right (maybe due to the annoying details of how those devices affect each other leaking into the general marshaling code).
Is there a more elegant way to handle this situation than a nest of conditionals determining behaviour? Or even a name for the situation or pattern?
Your scenario seems an ideal candidate for the visitor design pattern, with the following roles (see UML schema in the link):
objectStructure: your model, aka collection of Component
element: your Component base class
concreteElementX: your actual components (InputFilter, OutputFilter, Processor, ...)
visitor: the abstract family of algorithms that has to manage your model as a consistent set of elements.
concreteVisitorA: your configuration process.
Main advantages:
Your configuration/set-up corresponds to the design pattern's intent: an operation to be performed on the elements of an object structure. Conversely, this pattern allows you to take into consideration the order and kind of elements encountered during the traversal, as visitors can be stateful.
One positive side effect is that the visitor pattern will give your desing the flexibility to easily add new processes/algortihms with similar traversals but different purpose (for example: pricing of the system, material planning, etc...)
class Visitor;
class Component {
public:
virtual void accept(class Visitor &v) = 0;
};
class InputFilter: public Component {
public:
void accept(Visitor &v) override; // calls the right visitor function
};
...
class Visitor
{
public:
virtual void visit(InputFilters *c) = 0; // one virtual funct for each derived component.
virtual void visit(Processor *c) = 0;
...
};
void InputFilter::accept(Visitor &v)
{ v.visit(this); }
...
class SetUp : public Visitor {
private:
bool hasProcessor;
int impedenceFilter;
int circuitResistance;
public:
void visit(InputFilters *c) override;
void visit(Processor *c) override;
...
};
Challenge:
The main challenge you'll have for the visitor, but with other alternatives as well, is that the setup can change the configuration itself (replacing component ? change of order), so that you have to take care of keeping a consitent iterator on the container while making sure not to process items several time.
The best approach depends on the type of the container, and on the kind of changes that your setup is doing. But you'll certainly need some flags to see which element was already processed, or a temporary container (either elements processed or elements remaining to be processed).
In any case, as the visitor is a class, it can also encapsulate any such state data in private members.
Basically I have a base class called Geometry, and some derivative such as Point, Polygon, etc...
Geometry implements a method intersection like this :
Geometry* intersection(Geometry* other)
{
Geometry* inter = compute_intersection(this, other);
if (inter is a polygon)
return new Polygon(inter);
if (inter is a point)
return new Point(inter);
}
When I compute the intersection of two geometries in my program, I obtain a Geometry* and I can dynamic_cast it to whatever it really is.
Is it a good design ? What, I think, might be wrong is that I have to check real type each time I compute an intersection and dynamic_cast the result (which can be slow). But what I think is the main problem is that with this design, Geometry must know its derivative (Point, Polyline? etc...).
What could be a good solution to avoid these problems ?
Why do you need to construct a new object of the returned object, can't you jsut return it straight away? If you can not, just implement one additional method in each derivative class that wraps the result from compute_intersection in a new object and call this new method instead of compute_intersection in Geometry.
In my answer I assume the only possible situation: compute_intersection is abstract and each deriving class implements it.
If you find yourself needing to new according to inherited type to copy objects, then you can use virtual copy constructors, by implementing a clone() function that returns a copy of the object:
virtual Obj* Obj::clone() const { return new Obj(*this); }
This can be called from your intersection() function.
There are two issues here as far as I'm concerned.
Firstly, I don't care much for functions which get/set things. I'm more interested in telling objects to do something for me.
Secondly, you are trying to implement multiple dispatch (in this case double dispatch). This is where the behaviour you want depends upon the types of multiple objects.
My normal mantra of encapsulate, encapsulate, encapsulate guides me towards the following ideas:
Encapsulate what you want to do with the intersection e.g.
Put its area into a spreadsheet cell
Add geometry points to a display list
Encapsulate the dispatch of one type given another type
Look into the visitor pattern
Encapsulate applying the behaviour to an intersection
Perhaps you can use boost::variant:
typedef boost::variant<Point, Polygon/*, and other...*/> Geometry_Variants;
Geometry_Variants intersection(Geometry_Variants const& other)
{
// compute the intersection and return Point or Polygon
}
Your problem is known under the name: multiple dispatch or multi methods. There is no real good answer to this problem in C++ as far as I know. A good discussion of this problem by Andrei Alexandrescu is here:
http://books.google.fr/books?id=aJ1av7UFBPwC&pg=PA263&lpg=PA295&dq=modern+c%2B%2B+design+multiple+dispatch&source=bl&ots=YRdIZrWiaV&sig=2Vj0Blst_jmhMCAZIJ8gUiG_pl4&hl=fr&sa=X&ei=082XT86RHNS18QPW7f3mBQ&ved=0CCYQ6AEwAA#v=onepage&q&f=false
I recommend you to buy the book it's worth its price.
I've got a game engine where I'm splitting off the physics simulation from the game object functionality. So I've got a pure virtual class for a physical body
class Body
from which I'll be deriving various implementations of a physics simulation. My game object class then looks like
class GameObject {
public:
// ...
private:
Body *m_pBody;
};
and I can plug in whatever implementation I need for that particular game. But I may need access to all of the Body functions when I've only got a GameObject. So I've found myself writing tons of things like
Vector GameObject::GetPosition() const { return m_pBody->GetPosition(); }
I'm tempted to scratch all of them and just do stuff like
pObject->GetBody()->GetPosition();
but this seems wrong (i.e. violates the Law of Demeter). Plus, it simply pushes the verbosity from the implementation to the usage. So I'm looking for a different way of doing this.
The idea of the law of Demeter is that your GameObject isn't supposed to have functions like GetPosition(). Instead it's supposed to have MoveForward(int) or TurnLeft() functions that may call GetPosition() (along with other functions) internally. Essentially they translate one interface into another.
If your logic requires a GetPosition() function, then it makes sense turn that into an interface a la Ates Goral. Otherwise you'll need to rethink why you're grabbing so deeply into an object to call methods on its subobjects.
One approach you could take is to split the Body interface into multiple interfaces, each with a different purpose and give GameObject ownership of only the interfaces that it would have to expose.
class Positionable;
class Movable;
class Collidable;
//etc.
The concrete Body implementations would probably implement all interfaces but a GameObject that only needs to expose its position would only reference (through dependency injection) a Positionable interface:
class BodyA : public Positionable, Movable, Collidable {
// ...
};
class GameObjectA {
private:
Positionable *m_p;
public:
GameObjectA(Positionable *p) { m_p = p; }
Positionable *getPosition() { return m_p; }
};
BodyA bodyA;
GameObjectA objA(&bodyA);
objA->getPosition()->getX();
Game hierarchies should not involve a lot of inheritance. I can't point you to any web pages, but that is the feeling I've gather from the several sources, most notably the game gem series.
You can have hierarchies like ship->tie_fighter, ship->x_wing. But not PlaysSound->tie_fighter. Your tie_fighter class should be composed of the objects it needs to represent itself. A physics part, a graphics part, etc. You should provide a minimal interface for interacting with your game objects. Implement as much physics logic in the engine or in the physic piece.
With this approach your game objects become collections of more basic game components.
All that said, you will want to be able to set a game objects physical state during game events. So you'll end up with problem you described for setting the various pieces of state. It's just icky but that is best solution I've found so far.
I've recently tried to make higher level state functions, using ideas from Box2D. Have a function SetXForm for setting positions etc. Another for SetDXForm for velocities and angular velocity. These functions take proxy objects as parameters that represent the various parts of the physical state. Using methods like these you could reduce the number of methods you'd need to set state but in the end you'd probably still end up implementing the finer grained ones, and the proxy objects would be more work than you would save by skipping out on a few methods.
So, I didn't help that much. This was more a rebuttal of the previous answer.
In summary, I would recommend you stick with the many method approach. There may not always be a simple one to 1 relationship between game objects and physic objects. We ran into that where it was much simpler to have one game object represent all of the particles from an explosion. If we had given in and just exposed a body pointer, we would not have been able to simplify the problem.
Do I understand correctly that you're separating the physics of something from it's game representation?
i.e, would you see something like this:
class CompanionCube
{
private:
Body* m_pPhysicsBody;
};
?
If so, that smells wrong to me. Technically your 'GameObject' is a physics object, so it should derive from Body.
It sounds like you're planning on swapping physics models around and that's why you're attempting to do it via aggregation, and if that's the case, I'd ask: "Do you plan on swapping physics types at runtime, or compile time?".
If compile time is your answer, I'd derive your game objects from Body, and make Body a typedef to whichever physics body you want to have be the default.
If it's runtime, you'd have to write a 'Body' class that does that switching internally, which might not be a bad idea if your goal is to play around with different physics.
Alternatively, you'll probably find you'll have different 'parent' classes for Body depending on the type of game object (water, rigid body, etc), so you could just make that explicit in your derivation.
Anyhow, I'll stop rambling since this answer is based on a lot of guesswork. ;) Let me know if I'm off base, and I'll delete my answer.