OOP:组成样品请建议哪个更好,为什么

时间:2009-07-23 14:45:39

标签: c# oop composition

请忽略语言语法,我想在此讨论OOPS。


我将在这里展示2个代码片段,每个代码片段都是作文的样本(如果我没有错的话)。

问题陈述:我有一个对象,用于保存系统中实体的统计信息。让那些统计数据:

  1. 名称
  2. 名字
  3. 薪酬
  4. *这些字段可以是任何东西,我只是以这些为例。所以请不要考虑哪个领域是必要的。假设这三个都是必要的。

    我创建了一个与这些字段对应的类:

    public class Stats{
    field Name;
    field LatsName;
    field Salary;
    }
    

    现在我遇到了一种情况,我希望在一段时间内掌握一个人的信息。让我们看看工作流程系统中的某个点需要向其显示有关所有三个阶段的人的信息

    1. 他小时候。
    2. 他年轻的时候。
    3. 他退休的时候。
    4. 这里要注意的是namelastName不会改变,只有工资可能会改变。因此,我认为我可以创建一个可以使用现有对象'stats'的类。

      我要提出两个解决方案, 请建议哪个更好,为什么

      代码示例1

      public class CompositeStats{
        //Adding three more properties and hinding the one already existing.
        private objStats= new Stats();
        public field FirstName{
          get{return objStats.Name;}
          set{objStats.Name=value;}
        }
        public field LastName{
          get{return objStats.LastName;}
          set{objStats.LastName=value;}
        }
      
        public field SalaryChild{get;set;}
        public field SalaryYoung{get;set;}
        public field SalaryRetired{get;set;}
      }
      

      在上面的示例代码中,我没有公开工资的原始字段,但是每个时间跨度创建了3个新字段。

      代码示例2

      public class CompositeStats{
        private objStatsChild= new Stats();
        private objStatsYoung= new Stats();
        private objStatsRetired= new Stats();
      
        public field FirstName{
          get{return objStatsChild.Name;}
          set{objStatsChild.Name=value;}
        }
      
        public field LastName{
          get{return objStatsChild.LastName;}
          set{objStatsChild.LastName=value;}
        }
      
        public field SalaryChild{
          get{return objStatsChild.Salary;}
          set{objStatsChild.Salary=value;}
        }
      
        public field SalaryYoung{
          get{return objStatsYoung.LastName;}
          set{objStatsYoung.LastName=value;}
        }
      
        public field SalaryRetired{
          get{return objStatsRetired.LastName;}
          set{objStatsRetired.LastName=value;}
        }
      
      }
      

6 个答案:

答案 0 :(得分:2)

我觉得这样的事情会更好。它允许您在不改变对象模型的情况下创建新的生命阶段。

此外,如果某人尚未到达舞台,则不会存储任何信息。名为“CurrentStage”的属性可以选择列表中的最新阶段。

public class Stage{
  object BeginStage;  // Probably a DateTime or similar class.
  object EndStage;    // Probably a DateTime or similar class.
  object Salary;
}

public class Stats{
  object Name;
  object LastName;
  IEnumerable<Stage> Stages;
}

您也可以使用此变体。

public enum Stage {
  Child,
  Young,
  Retired,
}

public class StageSalary {
  Stage Stage;
  object Salary;
}

public class Stats{
  object Name;
  object LastName;
  List<StageInfo> Stages;
}

答案 1 :(得分:1)

让我们再考虑一下用法:

var dictStages = new Dictionary<Stage,double>();

此处,舞台是枚举:儿童,成人,退休

在您的课程中添加属性

CurrentStage - 这将从dictStage中重新选择最新阶段 CurrentSalary - 这将反映CurrentStage的工资。

尽管如此,您可能希望公开一些可以为特定阶段返回薪水的方法。

答案 2 :(得分:1)

我认为显而易见的是,第一个是更好的选择。

原因: 1.表现:

 private objStatsChild= new Stats();
private objStatsYoung= new Stats(); 
private objStatsRetired= new Stats();

为什么要创建三个实例,而实际上只需要来自其中一个实例的值。

  1. 糟糕的设计。 您正在创建三个“Stats”实例,并在返回名称时选择其中一个(随机,至少没有选择其中一个的逻辑)。
  2. 3.如果你想做的就是在统计数据中隐藏“薪水”,那么更多的是继承,从父类中删除“薪水”。

答案 3 :(得分:1)

检查一个名为"Facade"的设计模式,它允许您拥有一个继承自多个接口的单个​​类结构,并允许数据仅表示您将它们分类为的结构。即隐藏/忽略字段对于仅用于“退休”等的“孩子”。

答案 4 :(得分:0)

我会将您的代码重构为以下内容:

class Person {
   field Name;
   field LastName;
}

enum PersonAge {
   Child, Young, Retired
}

class Stage {
   public PersonAge Age { get; set; }
   field Salary;
}

class PersonStats {
   public Person Person { get; set; }
   public IList<Stage> Stages { get; set; }
}

有意义吗?

答案 5 :(得分:0)

“经典”“IsA”,“HasA”思维将始终帮助引导您朝着正确的方向前进:

“人物”“HasA”“数据集”,其中包含您生命阶段的信息。 今天你说“三个”阶段,但当然你永远不会设计出这样一个有限的问题视图......对吗?

所以你有

class Person {
  [vector or list or your favorite collection type] Data;
  Name;
  LastName;
};

您向Person询问有关“HasA”引用的快照,以及快照中您想要哪条数据的说明符:

class PersonInfoSnapshot {
  [reference to] Person;
  /* "reference to Person.Data" could mean anything that allows retrieval of the data that you need */
  [reference to] Person.Data;
};

作为练习留下的特定类型,可见性等的详细信息。