2011-04-29 64 views
6

我是一個主要與嵌入式設備(使用C和程序集編程)一起工作的開發人員。我的C#和麪向對象的知識是非常有限的(雖然我可以通過它在必要時通過它)。我有五個通過USB與PC連接的設備。 PC進行一些計算並將結果發送到設備。對每個設備執行相同的計算,但計算的結果是不同的。對於每個設備,我都有一個C#Windows Forms應用程序,它可以完成一些工作並將數據來回發送到設備。目前,我試圖將五個不同的應用程序合併爲一個,以便我們可以輕鬆地進行更改,輕鬆添加新設備,並擁有標準的用戶界面。我的問題是,我不完全知道這樣做的最佳方式,因爲我不知道在運行時間之前將使用哪個設備。我試圖避免一堆if語句,我希望能夠將每個設備放在一個單獨的文件中。這是我正在談論的一些psudo代碼。如何實現許多具有相同方法的類來完成不同的事情?

class Device //This is what EVERY device can do 
{ 
... 
DoWork1(); 
DoWork2(); 
DoWork3(); 
... 
} 

class Device1 
{ 
... 
DoWork1(); //This is how the work is done for this device 
DoWork2(); 
DoWork3(); 
... 
} 

class Device2 
{ 
... 
DoWork1(); //This is how the work is done for this device (not the same way as Device1) 
DoWork2(); 
DoWork3(); 
} 


public partial class frmMain : Form 
{ 
private (some kind of object or something) CurrentDevice; 
public frmMain() 
{ 
... 
//Determine what device (could be one of five) is currently being used 
CurrentDevice = (which device is currently being used) 
//Could be CurrentDevice = new Device1(); 
} 
} 

private void Button1_Click() 
{ 
CurrentDevice.DoWork1(); //But this could be Device1.DoWork1() or Device2.DoWork1(), depending on what device is currently being used (which was determined in the frmMain constructor) 
} 

我真的不知道,但我想我可以用一個接口或可能繼承設備類的Device1的類和重載的方法...但我不知道我會怎樣有一種通用的方式來表示CurrentDevice.DoWork1(),因爲CurrentDevice可能是Device1或Device2。

任何想法將不勝感激。我在Windows XP SP3和Windows 7上使用.NET 3.5的Visual Studio 2008.

我希望我能夠很好地描述問題。如果沒有,或者如果我沒有提到我應該的,請告訴我。我是新來的stackoverflow和C#。

謝謝

邁克爾

+0

我想感謝大家的幫助和建議。我決定採用西西弗斯提供的解決方案,因爲它適合我目前的應用。儘管每個人都有很好的意見,但我感謝你們。 :) – Michael 2011-04-30 00:30:39

回答

4

起初我有點困惑,因爲在這種情況下,PC不計算設備只接收的結果。所以,據我瞭解,你需要在PC上不同的實現,而不是設備本身。

這裏的真正訣竅不是使用接口或繼承 - 你已經知道了。訣竅是獲得正確的實現類型,併爲該部分使用工廠。

但是你必須決定繼承vs接口。

只有當「某些東西」真正屬於一個共同的,但也是有意義的家庭的一部分時才使用繼承。繼承應該有一個非常強大的「是」的元素。

OTOH許多物體可能存在,可能會做一個計算,但你可能不想做一個家庭。這是組成是有用的。要通過繼承來獲得它,你需要讓它們共享一個公共基類。在這裏你可以使用組合來允許每個對象使用一個通用接口來讓PC執行計算。

我建議這種方法。

您應該有一個對通用接口,IDoCalculation或某些類似接口的引用,這些接口定義了一個方法簽名,該方法簽名將以相同的方式用於任何設備。

接下來,您必須獲得該接口的設備特定實現,這是每個設備可以有不同實現的位置。爲每個設備類型/實現創建一個類。

現在的訣竅是讓你需要的課程,而不必知道它是什麼。要再次隱藏細節並使該方法調用通用,您可以創建一個參數化的工廠。該工廠接受描述計算機需要進行計算的設備的參數。然後它解釋該參數,並基於該參數創建一個實現IDCalculation的特定類。這是返回,你完成了。

我讓你找出這些對象需要如何組織成不同的組件......

//Common interface 
public interface IDoCalculation 
{ 
    //Use whatever method signatures you need 
    int DoCalculation(); 
} 

public class DeviceImplementation1 : IDoCalculation 
{ 


    #region IDoCalculation Members 

    public int DoCalculation() 
    { 
     //Device 1 Specific code goes here 
    } 

    #endregion 
} 

public class DeviceImplementation2 : IDoCalculation 
{ 


    #region IDoCalculation Members 

    public int DoCalculation() 
    { 
     //Device 2 Specific code goes here 
    } 

    #endregion 
} 

// A simple factory that does not require a lot of OOP understanding. 
public class DeviceCalculationFactory 
{ 
    //Return a correct implementor based on the device type passed in 
    public IDoCalculation GetCalculationImplementationInstance(string devicetype) 
    { 
     switch (devicetype) 
     { 
      case "Device1": 
       return new DeviceImplementation1(); 

      case "Device2": 
       return new DeviceImplementation2(); 
      default: 
       //TODO ??? 
       return null; 

     } 

    } 

} 

// A simple client that calls the methods and then send the results 
public class DeviceManager 
{ 
    //To do the calculation, get an implementor for the correct device type from the factory - Presumably the PC knows the device of interest, example "Device1" 
    public void DoTheCalculationThing(string deviceType) 
    { 


     DeviceCalculationFactory factory = new DeviceCalculationFactory(); 
     IDoCalculation calculation = factory.GetCalculationImplementationInstance(deviceType); 
     int result = calculation.DoCalculation(); 
     // now send the result to the device 

    } 

} 
1

您可能會感興趣的尋找一些設計模式這一點。 http://www.oodesign.com/

具體抽象工廠和模板方法。我認爲其中之一可能就是你要找的。 http://www.oodesign.com/abstract-factory-pattern.html
http://www.oodesign.com/template-method-pattern.html

據我瞭解,你希望能夠有一個基類,然後繼承基類的功能,在子類中定義它們。其中一種模式可能適用於您的場景。

+1

+1表示模板方法。這是要走的路。 @Anthony,你可以在你的抽象基類中有默認的實現,而冥想類只能覆蓋特定的方法。 – 2011-04-29 04:52:22

8

就你而言,你基本上定義了一個繼承層次結構,它可以由一個抽象基類和兩個派生類型組成,或者由一個具有兩個實現者的接口組成。例如

public abstract class BaseDevice 
{ 
    public abstract void DoWork1(); 
} 

public class Device1 : BaseDevice 
{ 
    public override void DoWork1() 
    { 
     // provide implementation here 
    } 
} 

// also create Device2 : BaseDevice and implement 

,或者你可以使用一個接口定義

public interface IDevice 
{ 
    void DoWork1(); 
} 

public class Device1 : IDevice 
{ 
    public void DoWork1() 
    { 
     // provide implementation 
    } 
} 

哪種方法你選擇是由你。例如,如果您想要定義一些行爲或屬性以及整個層次結構中常見的實現,您可能會喜歡抽象基類。使用抽象類,您可以提供實現。接口是一個空的契約,你不能提供任何常見的行爲,只能定義可能存在的行爲或屬性。

無論採用哪種方式,您都可以通過抽象或接口基引用更多派生類型的實例。以這種方式,你不關心實現類型是什麼,只是它可以做什麼(它是方法或屬性)。

例子:

BaseDevice device1 = new Device1(); 
BaseDevice device2 = new Device2(); 
// maybe you have a list? 
List<BaseDevice> devices = new List<BaseDevice> { device1, device2 }; 

foreach (BaseDevice device in devices) 
{ 
     device.DoWork1(); // notice you don't care about the actual type, just the behavior 
} 
0

安東尼Pegram的答案是優秀的,但你可能要採取這一步。可以想象的是,雖然看起來您的所有設備都在執行相同的任務,但您可能會發現有些設備實際上並不執行所有任務,其他人執行的任務甚至更多。

在這種情況下,你可能會改變以添加另一個DoWork5DoWork6方法,簡單地提高對各類NotImplemented異常不具有特定行爲的接口。

這很麻煩,原因很多。我會建議(如果你發現自己處於這個位置),請考慮明確你的角色。您可以通過創建代表特定角色的接口(或一組行爲 - 與接口隔離原則相關聯)來實現此目的。

所以你可以有IMediaPlayerPlayPauseRewind和另一IMediaRecorderRecord方法。這樣你就可以在你的具體類上實現相關的角色。

HTH

相關問題