面向对象的设计/设计模式场景

时间:2012-01-06 12:28:32

标签: c# .net oop design-patterns

我有3种不同类型的形状图说RectangleCubeCircle,我想为它们定义类,以便

  • 所有课程都有Title&颜色属性/方法,

  • Circle& Rectangle将有另外的方法Area,

  • 类似地,Cube将使用Volume方法而不是Area方法。

有一种方法可以获得'对象'的引用,下面是示例方法

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();
    }
}

如何在'ShapeClicked(object obj)'方法

中设计我的类
  • a)我不需要每次检查类型(应该在运行时发生),(这对我很重要,因为我有很多方法,比如'ShapeClicked'需要我检查类型)

  • b)如果对象是Circle,那么它只会获得Area方法,类似于Cube对象,它只能得到Volume方法。

我可以想到两种方法

  • 放入所有方法&基类中的属性&只覆盖派生类中的必需方法。创建一个Factory方法/类,它将返回Base类的引用。使用这种方法,我的'b'要求不符合

  • 只在基类和放大器中放置常用的方法/属性(如颜色)。在derive类中添加其他方法。这不能解决#a:(

有人能给我一些解决方案吗?#a& amp; #B

3 个答案:

答案 0 :(得分:3)

介绍一个新界面。

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(); }
}

更新

您的方法如下:

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();
}

答案 1 :(得分:0)

您应该拥有所有形状的基类,并且在基类中有一个方法ShapeClicked()

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()
}

然后将函数修改为:

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

通过多态性,您的呼叫将被定向到正确的类。

答案 2 :(得分:0)

当您有要继承的常见行为时,使用基类型是很好的。在您的情况下,您确实有一种与您的类型进行交互的常用方法,但这些行为的类型是完全不同的。

在这种情况下,您真正​​想要做的是定义一个通用界面,以便您可以类似地处理您的类型。

我会定义以下内容:

public interface IShape
{
    string Title { get; }

    string Color { get; }
}

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

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

然后,您可以在I2DShapeCircle以及Rectangle I3DShape上实施Cube。然后您的方法可以这样实现:

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();
    }
}

您仍然需要检查形状是2D还是3D,但这仅仅是因为我们将区域和体积定义为单独的东西。如果你想将它们定义为一个单一的东西,你可以把它放在基础接口上,让所有类型实现该接口。