如何构建具有多种输入和输出功能的嵌入式系统。一些基于硬件,一些基于软件设置
How to architect an embedded system with multiple input and output capabilities. Some based on hardware, some on software settings
我有一个在 Arduino 框架中编程的 ESP8266 项目,它从网络收集数据,然后显示在显示器上。该设备可以使用几种不同的显示硬件类型(eink、led、oled)构建。这些是在编译时使用#defines 设置的。然而,也有一些不同类型的数据和数据传输机制可以使用。有些需要硬件(LoRa TX/RX)并在编译时启用,但有些可以在运行时根据用户设置(例如 HTTP 或 MQTT)进行更改。
我已经在使用工厂设计模式在运行时实例化数据传输对象,但仍然使用编译时构建标志 select 来显示要使用的硬件。我有一个显示 class、一个数据源 class 和一个配置 class。此方法运行良好,但在我尝试添加蜂窝网络功能时已达到极限。
我想知道是否有一个好的设计模式/架构设计可以促进这种灵活性,而不必在我的代码中不断添加越来越多的侵入性 #ifdef 语句。
附件是这个设备的基本布局的小思维导图。
如果你想决定在运行时应该注入什么算法,那么你可以尝试使用策略模式。
正如 wiki 所说 strategy pattern:
In computer programming, the strategy pattern (also known as the
policy pattern) is a behavioral software design pattern that enables
selecting an algorithm at runtime. Instead of implementing a single
algorithm directly, code receives run-time instructions as to which in
a family of algorithms to use
所以你可以阅读你的配置文件并选择应该实例化的对象。比如你有很多显示器:
public enum DisplayMark
{
Samsung, Sony, Dell
}
然后你应该创建一个基础 class Display
:
public abstract class Display
{
public abstract string Show();
}
然后你需要这个基础的具体实现 class Display
:
public class SamsungDisplay : Display
{
public override string Show()
{
return "I am Samsung";
}
}
public abstract class SonyDisplay : Display
{
public override string Show()
{
return "I am Sony";
}
}
public abstract class DellDisplay : Display
{
public override string Show()
{
return "I am Dell";
}
}
到目前为止,还不错。现在我们需要像映射器这样的东西,它将负责通过从配置中选择的显示带来正确的实例:
public class DisplayFactory
{
public Dictionary<DisplayMark, Display> DisplayByMark { get; private set; }
= new Dictionary<DisplayMark, Display>
{
{ DisplayMark.Sony, new SonyDisplay()},
{ DisplayMark.Samsung, new SamsungDisplay()},
{ DisplayMark.Dell, new DellDisplay()},
};
}
然后当你从配置文件中知道应该使用什么显示器时,你就可以获得所需的实例:
public void UseDisplay(DisplayMark displayMark)
{
DisplayFactory displayFactory = new DisplayFactory();
Display display = displayFactory.DisplayByMark[displayMark];
// Here you can use your desired display class
display.Show();
}
我有一个在 Arduino 框架中编程的 ESP8266 项目,它从网络收集数据,然后显示在显示器上。该设备可以使用几种不同的显示硬件类型(eink、led、oled)构建。这些是在编译时使用#defines 设置的。然而,也有一些不同类型的数据和数据传输机制可以使用。有些需要硬件(LoRa TX/RX)并在编译时启用,但有些可以在运行时根据用户设置(例如 HTTP 或 MQTT)进行更改。
我已经在使用工厂设计模式在运行时实例化数据传输对象,但仍然使用编译时构建标志 select 来显示要使用的硬件。我有一个显示 class、一个数据源 class 和一个配置 class。此方法运行良好,但在我尝试添加蜂窝网络功能时已达到极限。
我想知道是否有一个好的设计模式/架构设计可以促进这种灵活性,而不必在我的代码中不断添加越来越多的侵入性 #ifdef 语句。
附件是这个设备的基本布局的小思维导图。
如果你想决定在运行时应该注入什么算法,那么你可以尝试使用策略模式。
正如 wiki 所说 strategy pattern:
In computer programming, the strategy pattern (also known as the policy pattern) is a behavioral software design pattern that enables selecting an algorithm at runtime. Instead of implementing a single algorithm directly, code receives run-time instructions as to which in a family of algorithms to use
所以你可以阅读你的配置文件并选择应该实例化的对象。比如你有很多显示器:
public enum DisplayMark
{
Samsung, Sony, Dell
}
然后你应该创建一个基础 class Display
:
public abstract class Display
{
public abstract string Show();
}
然后你需要这个基础的具体实现 class Display
:
public class SamsungDisplay : Display
{
public override string Show()
{
return "I am Samsung";
}
}
public abstract class SonyDisplay : Display
{
public override string Show()
{
return "I am Sony";
}
}
public abstract class DellDisplay : Display
{
public override string Show()
{
return "I am Dell";
}
}
到目前为止,还不错。现在我们需要像映射器这样的东西,它将负责通过从配置中选择的显示带来正确的实例:
public class DisplayFactory
{
public Dictionary<DisplayMark, Display> DisplayByMark { get; private set; }
= new Dictionary<DisplayMark, Display>
{
{ DisplayMark.Sony, new SonyDisplay()},
{ DisplayMark.Samsung, new SamsungDisplay()},
{ DisplayMark.Dell, new DellDisplay()},
};
}
然后当你从配置文件中知道应该使用什么显示器时,你就可以获得所需的实例:
public void UseDisplay(DisplayMark displayMark)
{
DisplayFactory displayFactory = new DisplayFactory();
Display display = displayFactory.DisplayByMark[displayMark];
// Here you can use your desired display class
display.Show();
}