2011-04-29 61 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

相关问题