4

我正在处理遗留代码,我已经看到了很多这样的代码:

public class Person
{
    public Person(PersonData data)
    {
        this.Name = data.Name;
        this.Gender = data.Gender ;
    }

    public String Name { get; private set;}
    public String Gender { get; private set;}
}

public class PersonData
{
    public String Name;
    public String Gender;
}

public static Person ReadPerson(Reader reader)
{
    PersonData data = new PersonData;
    data.Name = reader.ReadString();
    data.Gender = reader.ReadString();

    Person p = new Person(data);
    return p;
}

PersonData 类用于在其构造函数中设置 Person 类中的私有字段。除此之外,PersonData 类引入了冗余代码,正如您现在看到的那样,Person 和 PersonData 类中都有 Name 和 Sex。

在我看来,这种设计无法扩展:现在我有一个新字段“Age”要读取,我必须在两个不同的地方添加“Age”属性。

这是一个有效的设计选择(鉴于我在遗留代码中看到了很多这样的代码)?
我该如何重构呢?

编辑:

这两个类是真实代码的简化版本。所以请原谅使用字符串而不是枚举来表示性别。

在实际代码中,PersonData 有 10 多个字段,例如 Person 类。

4

5 回答 5

3

当使用构造函数注入时,使用参数对象是一种有效的方法,并且您开始在构造函数中获取大量参数 - 但是当您拥有的参数较少时,就没有必要了。

这是一个建议:

public class Person
{
    public Person(string name, string sex)
    {
        _name = name;
        _sex = sex;
    }

    public string Name { get {return _name; }}
    public string Sex { get {return _sex; }}

    private readonly string _name, _sex;
}

这使得类不可变

于 2012-11-17T01:11:14.683 回答
1

如果它是某种面向外部的对象(与您的情况似乎不同的数据传输对象),您可以考虑使用流畅的接口来构建它们,它不会减少类的数量,但会让您构造对象更花哨寻找方式以及更好地控制什么是必需的和什么是可选的。

如果有兴趣,请参阅带有fluent-interface标记的帖子。即条件生成器方法链接流畅接口

var person = PersonBuilder
  .CreatePerson()
    .Named(reader.ReadString())
    .Sex(reader.ReadString())
    .Build()
于 2012-11-17T01:36:14.240 回答
0

摆脱PersonData并将其提供Reader给构造函数:

public sealed class Person
{
    public Person(Reader reader)
    {
        this.Name = reader.ReadString();
        this.Sex = reader.ReadString();
    }

    public string Name { get; private set; }

    public string Sex { get; private set; }
}
于 2012-11-17T01:15:09.957 回答
0

一般来说,我会回到您正在建模的现实世界(或业务:))系统。如果该类与那个世界中的某些东西相匹配,那就没问题了。如果该类纯粹是编程系统的工件并且看起来也没有必要,我会扔掉它。使用“数据”类还可以隐藏使用显式参数会捕获的各种问题。例如,当您添加“年龄”时,您将如何检测是否找到了所有病例?如果将其添加为构造函数参数,则每个缺失的情况都会出现错误。

于 2012-11-17T01:22:43.407 回答
0

一种方法是代替

public String Name { get; private set;}
public String Sex { get; private set;}

暴露类型的属性PersonData

public class Person
{
    public PersonData PersonData { get; }
}

您也可以查看PersonPersonData.

于 2012-11-17T01:10:43.993 回答