Skip to content

Instantly share code, notes, and snippets.

@nuttycom
Last active January 8, 2017 21:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nuttycom/6e286855bc67b3d89096824eba33d531 to your computer and use it in GitHub Desktop.
Save nuttycom/6e286855bc67b3d89096824eba33d531 to your computer and use it in GitHub Desktop.
interface ShapeVisitor<A>
{
// The implementation of ApplyRect defines handling for the
// operation defined by this visitor in the case that the
// shape is a rectangle.
public A ApplyRect(IRectangle rect);
// The implementation of ApplyCircle defines handling for the
// operation defined by this visitor in the case that the
// shape is a circle.
public A ApplyCircle(ICircle circle);
}
public class AreaVisitor : ShapeVisitor<double>
{
public double ApplyRect(IRectangle rect)
{
return rect.height * rect.width;
}
public double ApplyCircle(ICircle circle)
{
return Math.PI * circle.radius * circle.radius ;
}
}
public class PerimeterVisitor: ShapeVisitor<double>
{
public double ApplyRect(IRectangle rect)
{
return 2 * (rect.height + rect.width);
}
public double ApplyCircle(ICircle circle)
{
return Math.PI * circle.radius * 2;
}
}
abstract class IShape {
public A accept<A>(ShapeVisitor<A> visitor);
// This becomes essentially syntactic sugar; it need not be defined as a method on the interface.
public double GetArea()
{
return accept(new AreaVisitor());
}
// I will not define GetPerimeter here - there is no purpose. The user
// can simply call myShape.accept(new PerimeterVisitor()) if they
// wish that functionality. The point here is that the end user can "extend"
// the interface by adding new Visitor implementations - they do not need
// IShape to be altered.
}
class ICircle : IShape {
public A accept<A>(ShapeVisitor<A> visitor) {
return visitor.ApplyCircle(this);
}
}
class IRectangle: IShape {
public A accept<A>(ShapeVisitor<A> visitor) {
return visitor.ApplyRect(this);
}
}
@giuliohome
Copy link

giuliohome commented Jan 8, 2017

Real word apps are full of types like double, string, etc and they're useful when you have to deliver an app within a deadline and you don't have time to add tons of code without any additional feature from the user perspective. Anyway, there is another point and it is related to the state handling. Let me explain it below.

Oh ... and this is a big problem: with a switch statement I can manage a mutable state IShape that is now Rectangle and then Circle. I don't see how it could be done with a Visitor, since I should accept a generic IShape and that's against the Visitor pattern in the first place. Have a look at my latest repository and tell me if you see any way - using C# as a language - to replace this switch with a Visitor?

Thank you again!

@giuliohome
Copy link

Never mind! Found and commited the changes to switch to a visitor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment