C# 什么';我应该使用s设计模式来概括类似类的用法吗?

C# 什么';我应该使用s设计模式来概括类似类的用法吗?,c#,.net,design-patterns,architecture,C#,.net,Design Patterns,Architecture,我有一些设备类,如以下示例: public class MoveSensor() { public uint GetData() { // Some logic here } } public class TemperatureSensor { public double GetData() { // Some logic here } } public class MultiSensorUnit() {

我有一些设备类,如以下示例:

public class MoveSensor() {
     public uint GetData() {
         // Some logic here
     }
}

public class TemperatureSensor {
     public double GetData() {
         // Some logic here
     }
}

public class MultiSensorUnit() {
     public MultiSensorData GetData() {
         // Some logic here
     }
}

public class MultiSensorData {
    public int SomeSensor1Data { get; set; }
    public byte SomeSensor2Data { get; set; }
    public double SomeSensor3Data { get; set; }
}
但我有一个类定期从这些设备收集数据:

public class DataCollector() {
     public void CollectData() {
         // Here I want to collect a data from all devices
     }
}
看起来我应该使用一个界面:

public interface IDataRecievable {
    [This is a problem place] GetData();
}

但是我不能这样做,因为GetData()从不同的设备返回不同的类型。我需要一种设计模式,使DataCollector中的设备使用更加通用。

您可以将返回数据的功能封装到同一接口的各种实现中。例如,如果将显示数据,则每个传感器返回不同类型的数据,以不同的方式显示数据。例如:

public interface Sensor {
    Data GetData();
}

public interface Data {
    void Display();
}

public class IntData : Data {
    public void Display() { ... }
}

public class DoubleData : Data {
    public void Display() { ... }
}

public class MoveSensor : Sensor {
    public IntData GetData() {
        // ... return IntData ...
    }
}

public class TemperatureSensor : Sensor {
    public DoubleData GetData() {
        // ... return DoubleData ...
    }
}
然后,一些客户端可以遍历每个传感器并显示数据:

List<Sensor> sensors = // ...

foreach (Sensor sensor in sensors) {
    sensor.Display();
}

其想法是将使用返回数据的责任从外部实体转移到数据本身。因此,
数据
实现最接近它存储的数据,因此,它应该负责处理它。如果有太多的事情需要通过
数据来完成,那么可以使用更复杂的技术,如处理程序或回调来将数据与数据处理分开。

您可以将返回数据的功能封装到同一接口的各种实现中。例如,如果将显示数据,则每个传感器返回不同类型的数据,以不同的方式显示数据。例如:

public interface Sensor {
    Data GetData();
}

public interface Data {
    void Display();
}

public class IntData : Data {
    public void Display() { ... }
}

public class DoubleData : Data {
    public void Display() { ... }
}

public class MoveSensor : Sensor {
    public IntData GetData() {
        // ... return IntData ...
    }
}

public class TemperatureSensor : Sensor {
    public DoubleData GetData() {
        // ... return DoubleData ...
    }
}
然后,一些客户端可以遍历每个传感器并显示数据:

List<Sensor> sensors = // ...

foreach (Sensor sensor in sensors) {
    sensor.Display();
}

其想法是将使用返回数据的责任从外部实体转移到数据本身。因此,
数据
实现最接近它存储的数据,因此,它应该负责处理它。如果有太多的事情需要通过
数据来完成,那么可以使用更复杂的技术,如处理程序或回调来将数据与数据处理分开。

这取决于每个传感器的结果。您已经给出了uint和double的示例。我猜其他传感器理论上可以返回字符串,甚至是复杂的复合对象

如果不知道传感器测量的是什么,那么来自传感器的答案是毫无意义的,而且这些数据的消费者显然知道。您的问题是否在DataCollector的中间存储中

我可以想象,在字典里,你会想要容纳任意数量的传感器及其结果。你能忍受装箱/拆箱的性能开销吗?如果没有大量的传感器,那么这应该可以忽略不计。如果是这样,您可以执行以下操作:

using System;
using System.Collections.Generic;
using System.Linq;

public interface IDataRecievable 
{
    object GetData();
}

public class PiSensor : IDataRecievable
{
     public object GetData() {
         return (object)3.14m;
     }
}

public class StringSensor : IDataRecievable
{
     public object GetData() {
         return (object)"Hello World";
     }
}


public class DataCollector
{

   private List<IDataRecievable> sensors;

   private Dictionary<Type, object> sensorResults = new Dictionary<Type, object>();

   public DataCollector(IEnumerable<IDataRecievable> sensorsToPoll)
   {
       this.sensors = sensorsToPoll.ToList();
   }

   public T GetResultFromSensor<T>(Type sensorType)
   {
      return (T)this.sensorResults[sensorType];
   }

    public void CollectData()
    {
        foreach (IDataRecievable sensor in this.sensors)
        {
            sensorResults[sensor.GetType()] = sensor.GetData();
        }           
    }    
}

public class Program
{       
    public static void Main()
    {
        List<IDataRecievable> sensors = new List<IDataRecievable>
        {
            new PiSensor(),
            new StringSensor()
        };          
        DataCollector dc = new DataCollector(sensors);    
        dc.CollectData();           
        decimal pi = dc.GetResultFromSensor<decimal>(typeof(PiSensor));
        string greeting = dc.GetResultFromSensor<string>(typeof(StringSensor));

        Console.WriteLine(2 * pi);
        Console.WriteLine(greeting);
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
公共接口IDataRecievable
{
对象GetData();
}
公共类PiSensor:IDataRecievable
{
公共对象GetData(){
返回(目标)3.14米;
}
}
公共类StringSensor:IDataRecievable
{
公共对象GetData(){
返回(对象)“你好世界”;
}
}
公共类数据采集器
{
专用传感器列表;
私有字典sensorResults=新字典();
公共数据采集器(IEnumerable sensorsToPoll)
{
this.sensors=sensorsToPoll.ToList();
}
公共T GetResultFromSensor(类型sensorType)
{
返回(T)this.sensorResults[sensorType];
}
公共数据()
{
foreach(此传感器中的IDataRecievable传感器)
{
sensorResults[sensor.GetType()]=sensor.GetData();
}           
}    
}
公共课程
{       
公共静态void Main()
{
列出传感器=新列表
{
新PiSensor(),
新传感器()
};          
DataCollector dc=新的DataCollector(传感器);
dc.CollectData();
十进制pi=dc.GetResultFromSensor(类型(PiSensor));
string greeting=dc.GetResultFromSensor(typeof(StringSensor));
控制台写入线(2*pi);
控制台。书写线(问候语);
}
}

这取决于每个传感器的结果。您已经给出了uint和double的示例。我猜其他传感器理论上可以返回字符串,甚至是复杂的复合对象

如果不知道传感器测量的是什么,那么来自传感器的答案是毫无意义的,而且这些数据的消费者显然知道。您的问题是否在DataCollector的中间存储中

我可以想象,在字典里,你会想要容纳任意数量的传感器及其结果。你能忍受装箱/拆箱的性能开销吗?如果没有大量的传感器,那么这应该可以忽略不计。如果是这样,您可以执行以下操作:

using System;
using System.Collections.Generic;
using System.Linq;

public interface IDataRecievable 
{
    object GetData();
}

public class PiSensor : IDataRecievable
{
     public object GetData() {
         return (object)3.14m;
     }
}

public class StringSensor : IDataRecievable
{
     public object GetData() {
         return (object)"Hello World";
     }
}


public class DataCollector
{

   private List<IDataRecievable> sensors;

   private Dictionary<Type, object> sensorResults = new Dictionary<Type, object>();

   public DataCollector(IEnumerable<IDataRecievable> sensorsToPoll)
   {
       this.sensors = sensorsToPoll.ToList();
   }

   public T GetResultFromSensor<T>(Type sensorType)
   {
      return (T)this.sensorResults[sensorType];
   }

    public void CollectData()
    {
        foreach (IDataRecievable sensor in this.sensors)
        {
            sensorResults[sensor.GetType()] = sensor.GetData();
        }           
    }    
}

public class Program
{       
    public static void Main()
    {
        List<IDataRecievable> sensors = new List<IDataRecievable>
        {
            new PiSensor(),
            new StringSensor()
        };          
        DataCollector dc = new DataCollector(sensors);    
        dc.CollectData();           
        decimal pi = dc.GetResultFromSensor<decimal>(typeof(PiSensor));
        string greeting = dc.GetResultFromSensor<string>(typeof(StringSensor));

        Console.WriteLine(2 * pi);
        Console.WriteLine(greeting);
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
公共接口IDataRecievable
{
对象GetData();
}
公共类PiSensor:IDataRecievable
{
公共对象GetData(){
返回(目标)3.14米;
}
}
公共类StringSensor:IDataRecievable
{
公共对象GetData(){
返回(对象)“你好世界”;
}
}
公共类数据采集器
{
专用传感器列表;
私有字典sensorResults=新字典();
公共数据采集器(IEnumerable sensorsToPoll)
{
this.sensors=sensorsToPoll.ToList();
}
公共T GetResultFromSensor(类型sensorType)
{
返回(T)this.sensorResults[sensorType];
}
公共数据()
{
foreach(此传感器中的IDataRecievable传感器)
{
sensorResults[sensor.GetType()]=sensor.GetData();
}           
}    
}
公共课程
{       
公共静态void Main()
{
列出传感器=新列表
{
新PiSensor(),
新传感器()
};          
DataCollector dc=新的DataCollector(传感器);
public class DataCollector
{
    public void CollectData()
    {
        var typesToRegister = Assembly.GetExecutingAssembly().GetTypes()
        .Where(type => !String.IsNullOrEmpty(type.Namespace))
        .Where(type => type.GetInterfaces().Any(x => x.IsGenericType 
                        && x.GetGenericTypeDefinition() == typeof(IDataRecievable<>)));

        foreach (var type in typesToRegister)
        {
            dynamic sensor = Activator.CreateInstance(type);
            sensor.CollectData();
        }
    }
}
public interface ICollectResultReceiver
{
    void ReceiveCollectResult(
        // whatever you are storing
        object someData
    );
}
public interface IDataRecievable<T>
{
    T GetData();
}

public interface IDataCollectable
{
    void CollectData(ICollectDataResultReceiver resultReceiver);
}
public interface IDataCollector
{
    void Add(IDataCollectable collectable);
    void CollectData();
}

public class DataCollector : IDataCollector
{
    private readonly ICollectDataResultReceiver _resultReceiver;
    private readonly List<IDataCollectable> _collectables = new List<IDataCollectable>();

    public DataCollector(ICollectDataResultReceiver resultReceiver)
    {
        _resultReceiver = resultReceiver;
    }

    public void Add(IDataCollectable collectable)
    {
        _collectables.Add(collectable);
    }

    public void CollectData()
    {
        foreach(var collectable in _collectables)
        {
            collectable.CollectData(_resultReceiver);
        }
    }
}
public interface IMoveSensorDataReceivable : IDataReceivable<uint> { }
public interface ITemperatureSensorDataReceivable : IDataReceivable<double> { }
public interface IMultiSensorDataReceivable : IDataReceivable<MultiSensorData> { }
public class MultiSensorData
{
    public uint GetSensorData1() => _moveSensor.GetData();
    public double GetSensorData2() => _temperatureSensor.GetData();

    private readonly IMoveSensorDataReceivable _moveSensor;
    private readonly ITemperatureSensorDataReceivable _temperatureSensor;

    public MultiSensorData(
        IMoveSensorDataReceivable moveSensor, 
        ITemperatureSensorDataReceivable temperatureSensor)
    {
        _moveSensor = moveSensor;
        _temperatureSensor = temperatureSensor;
    }
}
public class TestClass
{
    [Fact]
    public void MultiSensorDataTest()
    {
        var dummyTempSensor = new DummyTempSensor();
        var dummyMoveSensor = new DummyMoveSensor();
        var multiSensorData = new MultiSensorData(dummyMoveSensor, dummyTempSensor);

        Assert.Equal(10, multiSensorData.GetSensorData1());
        Assert.Equal(0.5, multiSensorData.GetSensorData2());
    }

    private class DummyTempSensor : ITemperatureSensorDataReceivable
    {
        public double GetData() => 0.5;
    }

    private class DummyMoveSensor : IMoveSensorDataReceivable
    {
        public uint GetData() => 10;
    }
}