Atul Sureka
Atul Sureka

Reputation: 3302

Object Oriented Design / Design Pattern scenario

I have 3 different type of shape diagrams say Rectangle, Cube, Circle, I want to define classes for them such that

There is a method in which I get the reference of of 'object', following is sample method

public void ShapeClicked(object obj)
{
// Check the type of obj & type cast it accordingly & call the method on that object
    object obj = new Circle();

    if (obj is Circle)
    {
        Circle circleObj  = (Circle)obj;
        circleObj.GetArea();
    }
    else if (obj is Rectangle)
    {
        Rectangle rectangleObj = (Rectangle)obj;
        rectangleObj.GetArea();
    }
    else if (obj is Cube)
    {
        Cube cubeObj = (Cube)obj;
        cubeObj.GetVolume();
    }
}

How can I design my classes such that in 'ShapeClicked(object obj)' method

I can think of two approaches

Can anybody suggest me some solution which solves both #a & #b

Upvotes: 2

Views: 1474

Answers (3)

jgauffin
jgauffin

Reputation: 101150

Introduce a new interface.

public interface IMeasurable
{
    someReturnType GetMeasure();
}

public class Circle : IMeasurable
{
    //some other methods

    public someReturnType GetMeasure() { return GetArea(); }
}

public class Cube : IMeasurable
{
    //some other methods

    public someReturnType GetMeasure() { return GetVolume(); }
}

Update

Your method would look like:

public void ShapeClicked(object obj)
{
    var measurable = obj as IMeasurable;
    if (measurable == null)
        throw new InvalidOperationException(string.Format("We can only work with measurable types, which {0} is not.", obj.GetType());

    var measure = measurable.GetMeasure();
}

Upvotes: 3

Paul Turner
Paul Turner

Reputation: 39615

Using base types is good when you have common behaviour you want to inherit. In your case, you really have a common way to interact with your types, but how those types behave is quite different.

In this case what you're really trying to do is define a common interface so you can treat your types similarly.

I would define the following:

public interface IShape
{
    string Title { get; }

    string Color { get; }
}

public interface I2DShape : IShape
{
    int GetArea();
}

public interface I3DShape : IShape
{
    int GetVolume();
}

You can then implement I2DShape on Circle and Rectangle, and I3DShape on Cube. Your method then can be implemented as such:

public void ShapeClicked(IShape shape)
{
    var shape2d = shape as I2DShape;

    if(shape2d != null)
    {
        shape2d.GetArea();
        return;
    }

    var shape3d = shape as I3DShape;

    if(shape3d != null)
    {
        shape3d.GetVolume();
    }
}

You still need to check whether a shape is 2D or 3D, but that's just because we've defined Area and Volume as separate things. If you wanted to define them as a singular thing, you could put that on the base interface and have all your types implement that interface.

Upvotes: 0

Luchian Grigore
Luchian Grigore

Reputation: 258568

Yes.

You should have a base class for all shapes and have a method ShapeClicked() in the base class.

class Shape 
{
-tile
-color
ShapeClicked()
}

class PlanarShape extends Shape
{
-area
Area()
}

class SpatialShape extends Shape
{
-volume
Volume()
}

class Circle extends PlanarShape
{
ShapeClicked()
}

class Rectangle extends PlanarShape
{
ShapeClicked()
}

class Cube extends SpatialShape
{
ShapeClicked()
}

Then you modify the function as:

public void ShapeClicked(Shape obj)
{
    obj.ShapeClicked();
}

Via polymorphism, your call will be directed to the right class.

Upvotes: 0

Related Questions