Design patterns 使用访问器:好还是坏?

Design patterns 使用访问器:好还是坏?,design-patterns,oop,Design Patterns,Oop,我有一个设计问题,我需要一些建议。假设我们在新的应用程序中需要(多么原始…)员工。我通常会这样做: public interface IEmployee { string EmployeeId { get; } string Name { get; } void Update(string newName, ...); ... } public class Employee : IEmployee { public Employee(string id,

我有一个设计问题,我需要一些建议。假设我们在新的应用程序中需要(多么原始…)员工。我通常会这样做:

public interface IEmployee
{
    string EmployeeId { get; }
    string Name { get; }
    void Update(string newName, ...);
    ...
}

public class Employee : IEmployee
{
    public Employee(string id, string name, ...)
    {

    }
    ...
}
TextBox nameTextBox = new TextBox();
...
nameTextBox.Text = employee.Name;
string name = nameTextBox.Text;
employee.Update(name, ...);
myEmployeeRepository.Save(employee);
这将从数据源获取员工

public class SqlEmployeeRepository : IEmployeeRepository
{
    ...

    public IEmployee GetEmployee(string id)
    {
        ...
        IEmployee employee = new Employee(id, name, ...);
        return employee
    }

    public IEmployee SaveEmployee(IEmployee employee)
    {
        // Execute SQL command.
    }
}
可视化将如下所示:

public interface IEmployee
{
    string EmployeeId { get; }
    string Name { get; }
    void Update(string newName, ...);
    ...
}

public class Employee : IEmployee
{
    public Employee(string id, string name, ...)
    {

    }
    ...
}
TextBox nameTextBox = new TextBox();
...
nameTextBox.Text = employee.Name;
string name = nameTextBox.Text;
employee.Update(name, ...);
myEmployeeRepository.Save(employee);
储蓄应该是这样的:

public interface IEmployee
{
    string EmployeeId { get; }
    string Name { get; }
    void Update(string newName, ...);
    ...
}

public class Employee : IEmployee
{
    public Employee(string id, string name, ...)
    {

    }
    ...
}
TextBox nameTextBox = new TextBox();
...
nameTextBox.Text = employee.Name;
string name = nameTextBox.Text;
employee.Update(name, ...);
myEmployeeRepository.Save(employee);
到目前为止,一切顺利。但是后来我运行了一篇文章,他们让我想知道没有getter的应用程序(静态和动态)会是什么样子,所以我尝试使用第二篇文章中描述的技术在没有getter的情况下实现上述应用程序。我想到了这个:

public interface IEmployee
{
    public interface Importer
    {
        string ProvideId();
        string ProvideName();
        ...
    }

    public interface Exporter
    {
        void AddId();
        void AddName();
        ...
    }

    void Export(IExporter exporter)
    ...
}

public class Employee : IEmployee
{
    private string _id;

    private string _name;

    public Employee(IEmployee.Importer importer)
    {
        _id = importer.ProvideId();
        _name = importer.ProvideName();
        ...
    }

    public void Export(IEmployee.Exporter exporter)
    {
        exporter.AddId(_id);
        exporter.AddName(_name);
        ...
    }
}
然后,存储库变为:

public class SqlEmployeeExporter : IEmployee.Exporter
{
    ...
    public void Save() { ... }
}

public class SqlEmployeeRepository : IEmployeeRepository
{
    ...

    public IEmployee GetEmployee(string id)
    {
        IEmployee.Importer importer = new SqlEmployeeImporter(id);
        IEmployee employee = new Employee(importer);
        return employee
    }

    public IEmployee SaveEmployee(IEmployee employee)
    {
        SqlEmployeeExporter exporter = new SqlEmployeeExporter();
        employee.Export(exporter);
        exporter.Save();
    }
}
可视化变成:

EmployeeNameTextBoxExporter exporter = new EmployeeNameTextBoxExporter();
employee.Export(exporter);
exporter.Render();
还有一些类似于储蓄的东西

虽然后一种实现消除了在
Employee
上使用getter的必要性,因此是更好的数据封装形式,但它似乎有点臃肿和过于复杂。你对这件事有什么看法?我是否遗漏或误解了文章中的某些内容?你对getter(和setter)的使用有什么总体看法


这个小实验让我现在倾向于使用访问器方法。也许你可以改变我的想法:-)

我认为访问器(getter和setter)要好得多,至少在你的例子中是这样。 我不认为在这里使用DTO模式有任何好处,最重要的是,代码变得不可读。编写好软件的关键之一是简单性:代码越简单,可读性和可维护性就越强。 通常,在解决问题时应使用模式。因此,您首先需要检测问题,然后应用最简单的模式解决问题。
使用DTO模式的选择应该得到以下事实的支持:它解决了一个特定的问题。

查看一个简短的代码片段自然会显得过于简单,不需要这样的封装。随着程序大小的增长,我可以看到这种方法在维护期间节省了时间。我对这种方法没有太多的经验,所以我无法给出一个明确的答案,但我认为它可以提供足够的好处,值得尝试和衡量结果

对于可读性,我认为这种方法比getter/setter有一些优势。假设您希望以表格的形式显示员工的工作计划。使用“构建器”方法,高级代码基本保持不变:

ScheduleDisplay display = new TableScheduleDisplay();
employee.Export(display);
display.Render();

这比指令列表更容易阅读,指令列表的主要目的是从一个对象中提取数据并将其放入另一个对象中。我一眼就知道,这段代码将计划显示为一个表

看起来你的
导出器
对象实际上是一个DTO:你提到的文章很有争议(特别是标题),应该谨慎对待:-)一般的理解是,他们并不反对getter/setter,只反对暴露不必要的getter/setter。已经就此进行了讨论,例如完全同意。我觉得这里的房子看起来更熟悉。可读性规则:)