如何实现许多具有相同方法的类来执行不同的操作?

Mic*_*ael 6 c# oop

我是一名主要从事嵌入式设备(用C和汇编编程)的开发人员.我的C#和OOP知识非常有限(尽管我可以在必要时伪造它).我有五个设备通过USB与PC连接.PC进行一些计算并将结果发送到设备.对每个设备执行相同的计算,但计算方式不同.对于每个设备,我都有一个C#Windows窗体应用程序,可以完成一些工作并将数据来回发送到设备.目前,我正在尝试将五个不同的应用程序合并为一个,这样我们就可以轻松地进行更改,轻松添加新设备,并拥有标准用户界面.我的问题是我不知道最好的方法,因为我不知道哪个设备将在运行时使用.我试图避免一堆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)
}
Run Code Online (Sandbox Code Playgroud)

我不是很确定,但我想我可以使用接口或者继承Device类的Device类并覆盖方法......但是我不知道怎么会有一种通用的方式说CurrentDevice .DoWork1()因为CurrentDevice可能是Device1或Device2.

任何想法将不胜感激.我在Windows XP SP3和Windows 7上使用Visual Studio 2008和.NET 3.5.

我希望我能很好地描述这个问题.如果没有,或者如果我没有提到我应该提到的东西,请告诉我.我是stackoverflow和C#的新手.

谢谢,

迈克尔

Ant*_*ram 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 
Run Code Online (Sandbox Code Playgroud)

或者您可以使用接口定义

public interface IDevice
{
    void DoWork1();
}

public class Device1 : IDevice
{
    public void DoWork1() 
    {
        // provide implementation 
    }
}
Run Code Online (Sandbox Code Playgroud)

您选择哪种方法取决于您.例如,如果您希望使用在整个层次结构中通用的实现来定义某些行为或属性,那么您可能会喜欢抽象基类.使用抽象类,您可以提供实现.接口是空契约,您不能提供任何常见行为,只能定义可能存在的行为或属性.

无论哪种方式,您都可以通过抽象或接口基础引用更多派生类型的实例.通过这种方式,您不关心实现类型是什么,只关心它可以做什么(它的方法或属性).

例:

 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
 }
Run Code Online (Sandbox Code Playgroud)


Sis*_*hus 4

一开始我有点困惑,因为在这种情况下,电脑进行计算,设备只接收结果。据我了解,您需要在 PC 上实现某些东西的不同实现,而不是设备本身。

这里真正的技巧不是使用接口或继承——你已经明白了。诀窍是获得正确的实现类型,并且您可以为该部分使用工厂。

但您也必须决定继承还是接口。

仅当该“某物”确实是一个共同且有意义的家庭的一部分时才使用继承。继承应该有一个非常强烈的“is a”元素。

OTOH 可能存在许多对象可以进行计算,但您可能不想创建一个族。这就是组合有用的地方。要通过继承实现这一点,您需要让它们共享一个公共基类。这里可以使用组合的方式让每个对象使用一个通用的接口来让pc来进行计算。

我建议采用这种方法。

您应该引用一个通用的通用接口、IDoCalculation 或类似的接口,它定义了一个方法签名,该方法签名将以相同的方式为任何设备调用。

接下来,您必须获取该接口的设备特定实现,这是每个设备可以有不同实现的地方。为每种设备类型/实现创建一个类。

现在的诀窍是获得您需要的课程,而不必知道它是什么。要再次隐藏细节并使方法调用通用,您可以创建参数化工厂。该工厂接受一个描述 PC 需要计算的设备的参数。然后它解释该参数并基于该参数创建一个实现 IDoCalculation 的特定类。该信息已返回,您就完成了。

我让您弄清楚如何将这些对象组织成不同的程序集......

//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

    }

}
Run Code Online (Sandbox Code Playgroud)