Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>The standard solution for this problem, especially given your constraints regarding dependencies, is to use the <a href="http://en.wikipedia.org/wiki/Visitor_pattern" rel="nofollow noreferrer">Visitor Pattern</a>.</p> <p>Here's how Visitor Pattern would work in your case:</p> <ul> <li>You need an abstract <code>ShapeVisitor</code> class. It has an abstract <code>Visit</code> method for each concrete subclass of Shape. eg: <code>Visit(Circle*)</code>, <code>Visit(Square*)</code>, etc.</li> <li>Shape has an abstract <code>AcceptVisitor(ShapeVisitor*)</code> method.</li> <li>Each Shape subclass implements <code>AcceptVisitor</code> as just calling <code>visitor-&gt;Visit(this)</code></li> <li>Each <code>CAD</code> class is a (or has-a, up to you) a <code>ShapeVisitor</code>. The <code>Visit</code> methods do the appropriate drawing for the specific type of <code>Shape</code>. No conditional or casting required.</li> </ul> <p>Here's a modified version of your code that uses Visitor Pattern in a pretty low-impact way:</p> <pre><code>class Circle; class Square; class ShapeVisitor { virtual void Visit(Circle *circle) = 0; virtual void Visit(Square *square) = 0; } class Shape { virtual void AcceptVisitor(ShapeVisitor *visitor) = 0; } class Circle : public Shape { // some special members/methods virtual void AcceptVisitor(ShapeVisitor *visitor) { visitor-&gt;Visit(this); } } class Square : public Shape { // some special members/methods virtual void AcceptVisitor(ShapeVisitor *visitor) { visitor-&gt;Visit(this); } } class CAD : public ShapeVisitor { virtual DrawCircle(Circle *circle) = 0; virtual DrawSquare(Square *square) = 0; virtual void Visit(Circle *circle) { DrawCircle(circle); } virtual void Visit(Square *square) { DrawSquare(square); } } class SWX : public CAD { virtual DrawCircle(Circle *circle){// do some stuff that draws circle on SWX system} } class PRO : public CAD { virtual DrawCircle(Circle * circle){// do some stuff that draws circle on PRO system} } int main() { Circle * circle = new Circle(); Square * sq = new Square; vector&lt;Shape*&gt; shapes; shapes.push_back(circle); shapes.push_back(sq); SWX * swx = new SWX(); for( int i = 0 ; i &lt; shapes.size() ; ++i ) { shapes[i]-&gt;AcceptVisitor(SWX); } } </code></pre> <p>In this code I've opted for making <code>CAD</code> actually a subclass of <code>ShapeVisitor</code>. Also, since you've already got virtual methods in <code>CAD</code> to do the drawing, I implemented the <code>Visit</code> methods there (once), rather than once in each subclass. Once you switch clients over to the using <code>AcceptVisitor</code> instead of calling the Draw* methods directly you could make those methods protected, and then eventually move the implementation of the <code>Visit</code> methods down to the subclasses (that is: refactor to remove the extra level of indirection caused by having <code>Visit(Foo*)</code> call <code>DrawFoo(Foo*)</code>).</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