2012-01-06 94 views
3

我有3个不同类型的形状图表说RectangleCubeCircle,我想为它们定义,使得面向对象设计/设计模式的情况下

  • 所有类的类将有标题& Color属性/方法,

  • 圈&矩形将有更多的方法区,

  • 同样竟被魔方d有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(obj对象)”方法

  • 一)我不必每次检查的类型(应该在运行时发生),(这对我来说很重要,因为我有很多方法,如“ShapeCli cked”这需要我核对型号)

  • B)如果对象是圆的话,那就只能得到区域的方法,同样的立方体对象,将只能得到体积法。

我能想到的把所有的方法在基类&在派生类才覆盖所需的方法&性质两种方法

  • 。创建一个工厂方法/类,它将返回基类的引用。通过这种方法,我的'b'要求不符合

  • 仅在基类&中添加常用方法/属性(如颜色),以便在派生类中添加其他方法。这并不能解决#A :(

可有人建议我一些解决方案,解决了这两个#A#B &

+0

这是真正的代码还是只是一个任意的样本?现在你的示例是从形状中获取一个数字,但是你没有显示你用它做了什么。 – tcarvin 2012-01-06 14:00:39

回答

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

感谢您的回应,您已将'GetMeasure'方法添加到cicle和cube,并从那里调用其各自的方法。我有很多像GetVolume/GetArea一样的方法,一些对于圆,多维数据集和其余部分都是特定于该类的。如何解决我在问题中提到的#a&#b? – 2012-01-08 01:35:31

+0

在基类中实现不可测量性。 – jgauffin 2012-01-08 11:25:55

+0

你能否回答http://stackoverflow.com/questions/9511137/is-the-solution-design-optimal-c-sharp-3-tier? – Lijo 2012-03-01 05:42:27

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

通过多态性,您的调用将被引导到正确的类。

+0

-1否它会违反“是-A”关系。界面(组合)是优选的。 – jgauffin 2012-01-06 12:36:15

+0

@jgauffin它是如何影响is-a关系的? – 2012-01-06 12:40:38

+0

@LuchianGrigore Atul正在C#工作。你已经给了java代码:) – 2012-01-06 12:43:42

0

使用基本类型是不错的,当你有你想要继承共同的行为。在你的情况下,你真的有一种常见的方式来与你的类型进行交互,但这些类型的行为是完全不同的。

在这种情况下,你真正要做的是定义一个通用接口,以便类似地处理你的类型。

我将定义如下:

public interface IShape 
{ 
    string Title { get; } 

    string Color { get; } 
} 

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

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

然后,可以按CircleRectangleI3DShape实施I2DShapeCube。你的方法则可以实现为这样:

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,但是这只是因为我们定义的面积和体积作为单独的东西。如果你想将它们定义为单一事物,你可以将它放在基础接口上,并让所有类型实现该接口。

+2

基于类型编写条件代码的问题是可扩展性。如果以后我们需要另一种形状,我们有很多工作要做。 – 2012-01-06 12:56:22

+0

这取决于您在面积和体积中添加的其他方法。一维(长度),二维(面积)和三维(体积)似乎涵盖了所有已知的图表暗示:)我喜欢这个建议,如果它适合你所面临的更广泛的问题,但是你不得不举出更多的例子。 – tcarvin 2012-01-06 13:51:28

+0

如前所述,如果您考虑面积和体积不同的事情(如理智的人),则只需进行类型检查。如果你想把它们当作相同的信息,你可以创建一个'GetAreaOrVolume'方法来表示基于'IShape'接口的两个东西。 – 2012-01-06 16:25:14