[英]Call a method on a class or pass as a parameter to another class? C#
假設我正在使用'Job'類記錄一些數據。 (具有各種屬性的業務對象列表,用於它的價值。)
我希望能夠打印這些數據,所以我想知道是否有更優選的設計來做到這一點。 我目前有兩個想法 - 在Job本身上調用Print()方法,或者將Job實例傳遞給某種類型的打印控制器類,例如:
job.Print();
要么
PrintWidget pw = new PrintWidget(job);
pw.Print();
目前,我無法設想打印此Job類中的數據以外的任何內容。 但是,誰知道未來會怎樣。 考慮到這一點,在我想要打印的任何類上使用單獨的Print()方法,或者可以處理不同類型的東西打印的一個Print控制器類會更好嗎?
你會如何設計呢? 提前感謝您的任何答案。
您的問題完全符合單一責任原則(SRP) ,即SOLID原則之一。
該原則基本上表明,精心設計的組件應該只負責單個任務。 另一種看待它的方式是組件應該只有一個改變的理由。 這可以確保當您需要更改某些內容時,您知道所有功能都將在一個位置, 並且不會與其他功能混合使用 。
在您的情況下, Job
可能具有除打印之外的某種功能,或許在您的域模型中表示“作業”的一些職責。 如果是,那么您不想在此處添加打印功能。 而是創建您的打印小部件並將所有邏輯用於打印。
如果您的打印必須更改,您不必觸摸您的Job
對象,因為它的職責沒有改變。 同樣,如果“作業”的概念發生變化,則僅修改Job
類,並且打印保持不受影響(除非您現在有額外的東西要打印)。
然而...
如果Job
類的唯一目的是表示一些打印信息,那么它絕對應該包含PrintTo(Printer)
方法,其中Printer
將負責與物理打印機通信。 在這種情況下,責任已轉移到僅涉及打印的Job
,並且它應該控制它的打印方式。
在您的設計中,SRP可能是一種難以看到的模式,但有一種簡單的方法可以確定:
如果您可以在不使用單詞“and”的情況下總結類的功能,則該類具有單一的責任。
因此, Job
負責“代表工作”或“打印工作信息”,但不是兩者都有。
打印知識是您Job
類的關鍵部分嗎? 如果沒有,它可能不應該在那個班級(關注點分離等)。 如果在不同的環境中打印可能不同,則這適用於雙重情況。 我可能會做更像的事情:
PrintWidget pw = new JobPrintWidget(); // perhaps via abstract-factory
pw.Print(job);
至於PrintWidget
是什么...如果你將來需要支持其他類型,我猜你可能要么具有抽象基類的具體實現(如上所示,其中Print
是抽象方法),或者替代一個界面。
對我來說,工作感覺更像輸入,但如果小部件只需要打印1個工作,那就這樣吧。
另一種可能性(在C#3中)是一種擴展方法:
static class PrintUtil {
public static void Print(this Job job) {...}
}
這允許你使用job.Print()
,但不將代碼放入Job
。
一種選擇是使用在C#3.0中引入的擴展方法 。 擴展方法允許您擴展類而不從中派生,這允許更大的靈活性。 使用擴展方法,您可以將Job方法添加到Job類和任何其他類,而無需更改原始類。 例如:
static class PrintExtensions
{
public static void Print (this Job job)
{
// TODO: print Job
}
public static void Print (this SomeOtherClass c)
{
// TODO: print SomeOtherClass
}
}
一旦定義了擴展方法,就可以像在類本身上定義一樣使用它,例如:
Job job = GetJob();
job.Print(); // call PrintExtensions.Print(this Job job)
就個人而言,我會將Print方法放在Job類中。 如果您創建一個單獨的PrintWidget類,則必須知道有關Job類的所有內容。 無論如何,如果事實證明您將來確實需要或想要一個PrintWidget,那么您可以隨時創建它並將Job類的Print方法重構為它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.