课堂设计问题

时间:2010-07-30 16:20:08

标签: c# class-design

假设我想创建一个HumanBody类。 我想存储每个肢体的长度。

HumanBody.LeftArmLength = 14;
HumanBody.RightArmLength = 14.1;
HumanBody.LeftLegLength = 32;
HumanBody.RightLegLength = 31.9;

这一切都很好,但似乎做出类似的事情会更好:

HumanBody.Arm.Left.Length = 14;
HumanBody.Arm.Right.Length = 14.1;
HumanBody.Leg.Left.Length = 32;
Humanbody.Leg.Right.Length = 31.9;

所以这将涉及制作子类。我正在描述被认为是“良好实践”的东西吗?看起来这是一种更有条理的存储数据的方式。

编辑:这个例子很简单,但是如果要存储100个不同的数据,这似乎是一个更好的方法。

10 个答案:

答案 0 :(得分:10)

左臂和右臂是Arm的实例,所以也许:

HumanBody.LeftArm.Length = 14; 
HumanBody.RightArm.Length = 14.1; 
HumanBody.LeftLeg.Length = 32; 
Humanbody.RightLeg.Length = 31.9; 

据推测,你需要考虑某人可能没有双臂或双腿的情况。

[注意:正如评论中所指出的,理想情况下,这些应该在构造函数中设置,而不是使用属性。这是一般原则:以连贯,可用的状态构造对象。]

答案 1 :(得分:8)

这取决于真实的情况。在将两个手臂组合在一起并将两条腿放在一起时,似乎没有非常多点......“一对手臂”的概念通常不是很有用。< / p>

另一方面,如果您正在谈论将“DeliveryAddress1”,“DeliveryAddress2”,“DeliveryTown”,“DeliveryZipCode”,“BillingAddress1”,“BillingAddress2”,“BillingTown”和“BillingZipCode”分组为两个实例一个Address类,这是另一回事。

基本上,个别部分是否属于自然分组?这个组是否可能需要以复合方式处理?你能看到自己将小组传递给其他一些代码吗?如果是这样,那听起来像是一个很好的封装单位。如果没有,也许你只是不必要地使事情变得复杂......

答案 2 :(得分:3)

你可能有

HumanBody.LeftArm.Length

您的课程类似于:

public class HumanBody
{
    public Arm LeftArm { get; private set; }
}

public class Arm
{
    public double Length { get; private set; }
}

但我没有看到你的手臂属性的优势

public class HumanBody
{
    public Arms Arm { get; private set; }
}

public class Arms
{
    public Arm Left { get; private set; }
    public Arm Right { get; private set; }
}

public class Arm
{
    public double Length { get; private set; }
}

我看不出那个模型是如何与人体的有用设计相匹配的(你是否会对另一个物体说“这是这个人体的两个臂”?)。基本上没有理由从较小的部件组成物体,除非这些部件本身是合理的单元。有一个论点,一个手臂是一个单独的类,一对手臂不那么。

我认为它还取决于层次结构的深度和宽度。在我上面给出的例子中,没有真正的收获。你已经用一个包含单个double的类替换了一个double属性,可能稍微更清晰,但肯定没有更多的功能。另一方面,情况如下:

HumanBody.LeftArm.Forefinger.Length = 3.2

使自己的成分更容易辨认(并且功能较少)

HumanBody.LeftArmsForefingerLength = 3.2

答案 3 :(得分:2)

你的主要目标是什么?在我看来,它是HumanBody,并且附肢长度只是其中的属性。

如果你认为你会找到很多拥有两个以上武器的人类,那么无论如何都要有一个Arms集合: - )

但我认为你能够为你的例子摆脱你的第一个解决方案。一旦一个对象开始获得数百个属性,那么,是的,您应该考虑以更分层的方式组织它。至于最好的方法,我们必须看到您的实际要求。

答案 4 :(得分:1)

选择任何一个都没有广泛的规则。这个决定实际上归结为属性是否真正与主类相关联,或者您是否认为需要将属性划分为单独的类,以便这些类可以自行传递和操作。

顺便说一句,我知道你的例子是相当人为的,但第二个暗示HumanBody只有一只手臂,只有一条腿有左侧和右侧。在这种特殊情况下,最好使用返回其各自类实例的RightArmLeftArmRightLegLeftLeg属性。当然,如果您想要与肢体相关联的唯一属性是它们的长度,那么这会让您回到第一个示例...只是需要考虑的食物。

答案 5 :(得分:0)

设置对象层次结构取决于您的需求。有时它是有道理的,有时却没有。

例如:

//This make sense
public class Person {

    public String FirstName { get; set; }
    public String LastName { get; set; }
    public String FullName
    {
        get { return String.Format("{0} {1}", FirstName, LastName); }
    }

    public Address Address { get; set; }
    public PhoneNumber[] ContactNumbers { get; set; }
}

//This does not make as much sense, but it's still possible.
public class Person {
    public Name Name { get; set; }
    public Address Address { get; set; }
    public PhoneNumber[] ContactNumbers { get; set; }
}

第二个例子没有多大意义,因为Name对象似乎不是它们将被重用的对象类型,但它只是容器中的容器。所以这样做是可以的,但就我个人来说,我会做第一种方法。

答案 6 :(得分:0)

这取决于你如何使用偏侧性。如果你的功能需要同时在身体的整个身体上进行操作,你可能会有这样的事情:

class Bilateral
{
    Arm arm;
    Leg leg;
    Eye eye;
    Ear ear;
    ...
}

class HumanBody
{
    Bilateral left, right;
    Liver liver;
}

所以你会做HumanBody.liver.weight = 3.14;HumanBody.left.arm.length = 12.34;

答案 7 :(得分:0)

我认为将人体限制在左右手臂是短视的。有些人没有武器。有些人只有右臂。如果一个人的手臂从前面传来更多怎么办?

当然,我们也可以将这些原则应用于腿部。

关于限制构造器的长度,是否考虑了假体?

答案 8 :(得分:0)

我认为这里的构图最有意义,但我建议动态构图而不是静态构图,以便解释解剖异常(缺失肢体等)

public abstract class Body
{
   public Dictionary<string, BodyPart> BodyParts { get; set; }
   //other properties, methods, etc.
}

您的BodyPart类可能纯粹是虚拟的......

public abstract class BodyPart
{
}

您可以添加特定类型的身体部位:

public abstract class Limb : BodyPart
{
   public float Length { get; set; }
   public abstract void Move();
}

如果需要,可以为手臂,腿等创建子类

public class Arm : Limb
{
   public override void Move()
   {
      Debug.WriteLine("Arm is moving");
   }
}

最后,您可以将您的身体子类化为特定于人类:

public class HumanBody : Body
{
   //properties and methods specific to the human body
}

总而言之,您可以动态创建健壮的HumanBody:

HumanBody body = new HumanBody();
Arm leftArm = new Arm(){ Length=24F };
Arm rightArm = new Arm(){ Length=24F };
//create other parts
body.BodyParts.Add(new KeyValuePair<string, BodyPart>("LeftArm",leftArm));
body.BodyParts.Add(new KeyValuePair<string, BodyPart>("RightArm",rightArm));
//add other parts

虽然这是非常灵活的,但明显的缺点是,如果你真的想要使用任何身体部位,你将不得不进行大量的施法:

Arm leftArm = body.BodyParts["LeftArm"] as Arm;
leftArm.Move();

对于2行代码来说还不错,但是如果你需要协调运动,那么增加的投射开销可能会非常繁重。

那是我的2c。

答案 9 :(得分:-1)

只是为了把我的两分钱投入到我的投票中,我们默许了人类的自然双重对称:

public class Digit { public double Length { get; set; } }

public class HumanSide
{
    public Digit Arm { get; set; }
    public Digit Leg { get; set; }
    public Digit MiddleFinger { get; set; }
    public Digit Foot { get; set; }
    public Digit Nose { get; set; }
}

public class Human
{
    public HumanSide Right { get; set; }
    public HumanSide Left { get; set; }
}
相关问题