2010-09-10 66 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