Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I actually think that the visitor pattern would be misused here. Instead, this is a classic switch-on-types code smell that is best handled by polymorphism.</p> <p>When you say "what if one derived class has an additional method to call", that is assuming a specific design. That is not a functional requirement. A functional requirement would be "what if one of the two objects created had to do behavior X during event Y". Why is this different? Because there are a number of ways to implement this that don't require more interface (though maybe more methods).</p> <p>Let me show an example.</p> <p>You have your factory</p> <pre><code>std::map&lt;ConfigValue, Generator&gt; objectFactory_; </code></pre> <p>That you've registered a bunch of generators for (probably in constructor of class)</p> <pre><code>RegisterGenerator(configValueA, DummyGenerator); RegisterGenerator(configValueB, RealGenerator); ... </code></pre> <p>And at some point you want to create one of those objects.</p> <pre><code>shared_ptr&lt;Base&gt; GetConfigObject(ConfigFile config) { return objectFactory_[config.a](); } </code></pre> <p>And then you want to use the object for handling an event, you can do</p> <pre><code>void ManagingClass::HandleEventA() { theBaseObjectReturned-&gt;HandleEventAThroughInterfaceObject(this); } </code></pre> <p>Note how I passed a this pointer. This means if you have one object that doesn't want to do anything (like make that extra behavior call) that your managing class may provide, it doesn't need to use this.</p> <pre><code>Object&lt;DummyInterface&gt;::HandleEventAThroughInterfaceObject(ManagingClass *) { // just do dummy behavior } </code></pre> <p>And then if you want to do something extra (call a new behavior) it can do it through that pointer in the RealInterface</p> <pre><code>Object&lt;RealInterface&gt;::HandleEventAThroughInterfaceObject(ManagingClass * that) { that-&gt;DoExtraBehavior(); // then dummy - or whatever order // you could even call multiple methods as needed } </code></pre> <p>That's the basic approach you should always take when dealing with polymorphism. You should never have two different code paths for different types except through calls to virtual dispatch. You should never have two different code blocks, one that calls methods A, B, and C and another that only calls A and D when dealing with a base object, depending on type. Instead, always make the derived objects do the work of figuring out what to do - because they know who they are. If you need to do stuff in the managing object, pass a this pointer for them to work with.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload