2010-09-10 39 views
4

我有一个设计问题,我可以使用一些建议。假设我们需要(如何原创......)我们的新应用程序中的员工。我通常会做的是这样的:使用访问器:好还是坏?

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

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

    } 
    ... 
} 

这从数据源中获取员工

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. 
    } 
} 

可视化将是这个样子:

TextBox nameTextBox = new TextBox(); 
... 
nameTextBox.Text = employee.Name; 

和保存会看像这样:

string name = nameTextBox.Text; 
employee.Update(name, ...); 
myEmployeeRepository.Save(employee); 

到目前为止,这么好。但后来我运行了thisthis文章,他们让我不知道应用程序在没有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(); 

而且东西similair用于保存。

虽然后者的实现删除了获取者对Employee的必要性,因此是更好的数据封装形式,但它也似乎有点臃肿和过于复杂。你对这件事有什么看法?我是否缺少或误解文章中的某些内容?你对使用吸气剂(和吸附剂)有何一般意见?

这个小实验让我倾向于现在使用accessor方法。也许你可以改变主意:-)

+0

看来你的'出口商'对象实际上是一个DTO:http://en.wikipedia.org/wiki/Data_transfer_object – Sjoerd 2010-09-10 07:41:28

+0

你提到的文章是相当有争议的(特别是标题),应该用捏盐:-)共同的理解是,他们一般不反对getter/setters,而只是针对暴露_unnecessary_ getters/setters。这已经在SO上进行了讨论,例如http://stackoverflow.com/questions/2747721/getters-and-setters-are-bad-oo-design,http://stackoverflow.com/questions/565095/java-are-getters-and-setters-evil – 2010-09-10 07:50:12

回答

1

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

为了便于阅读,我认为这种方法比getters/setter有一些优点。假设您想要将员工的工作时间表显示为表格。使用“建设者”的办法,高层次的代码大部分保持不变:

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

这是很容易超过其主要目的是从一个对象中提取数据,并将其放置到另一个物体的指令列表阅读。我一眼就知道这段代码将时间表显示为一张表。

3

我认为访问器(getters和setters)好得多,至少在你的例子中。 这里我没有看到使用DTO模式的优点,最重要的是,代码变得不可读。一个关于编写好软件的关键是简单性:代码越简单,可读性和可维护性就越高。 一般来说,应该在解决问题时使用模式。所以你首先需要检测一个问题,然后用解决问题的最简单模式解决问题。 使用DTO模式的选择应该由它解决特定问题的事实来支持。

+0

完全同意。我认为属性看起来更熟悉。可读性规则:) – dmitko 2010-09-10 08:05:37