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;
}
}