C#嵌入x汇编——一个GPIO接口的实现

📅 发布时间:2026/7/6 9:13:10 👁️ 浏览次数:
C#嵌入x汇编——一个GPIO接口的实现
托中媒露在日常开发中我们经常会遇到需要根据不同条件执行不同逻辑的场景导致代码中出现大量的if/else嵌套。这不仅降低了代码的可读性和可维护性还会增加后续扩展的难度。本文将介绍四种优雅的设计模式来优化这种条件爆炸问题1 策略模式01 概念首先我们来看下策略模式的定义。策略模式Strategy Pattern是行为型设计模式之一它定义了一系列算法并将每个算法封装起来使它们可以相互替换。 策略模式使得算法可以独立于使用它们的客户端变化。怎么理解策略模式 软件开发中常常遇到这种情况实现某一个功能有多种算法或者策略我们需要根据环境或者条件的不同选择不同的算法或者策略来完成该功能。这么一看不就是 if...else...的逻辑 图中的实现逻辑非常简单当我们是初学者时这样写没有问题只要能正常运行即可。但随着经验的增长这段代码明显违反了 OOP 的两个基本原则单一职责原则一个类或模块只负责完成一个职责或功能。开闭原则软件实体模块、类、方法等应该“对扩展开放对修改关闭”。由于违反了这两个原则当 if-else 块中的逻辑日益复杂时代码会变得越来越难以维护极容易出现问题。策略模式的设计思路是定义一些独立的类来封装不同的算法每一个类封装一个具体的算法。每一个封装算法的类我们都可以称之为策略 (Strategy) 为了保证这些策略的一致性一般会用一个抽象的策略类来做算法的定义而具体每种算法则对应于一个具体策略类。这种设计思想里包含三个角色Context: 环境类Strategy: 抽象策略类ConcreteStrategy: 具体策略类对应的时序图接下来我们用代码简单演示一下。02 例子步骤 1创建接口public interface Strategy {public int doOperation(int num1, int num2);}Strategy 接口定义了一个 doOperation 方法所有具体策略类将实现这个接口以提供具体的操作。步骤 2创建实现相同接口的具体类OperationAdd 是一个具体的策略类实现了加法操作。public class OperationAdd implements Strategy{Overridepublic int doOperation(int num1, int num2) {return num1 num2;}}OperationSubtract 是另一个具体的策略类实现了减法操作。public class OperationSubtract implements Strategy{Overridepublic int doOperation(int num1, int num2) {return num1 - num2;}}OperationMultiply 是第三个具体的策略类实现了乘法操作。public class OperationMultiply implements Strategy{Overridepublic int doOperation(int num1, int num2) {return num1 * num2;}}步骤 3创建上下文类public class Context {private Strategy strategy;public void setStrategy(Strategy strategy) {this.strategy strategy;}public int executeStrategy(int num1, int num2) {return strategy.doOperation(num1, num2);}}Context 类持有一个策略对象的引用并允许客户端设置其策略。它提供了一个 executeStrategy 方法用于执行策略并返回结果。步骤 4使用上下文来看到策略改变时的行为变化public static void main(String[] args) {Context context new Context();context.setStrategy(new OperationAdd());System.out.println(10 5 context.executeStrategy(10, 5));context.setStrategy(new OperationSubstract());System.out.println(10 - 5 context.executeStrategy(10, 5));context.setStrategy(new OperationMultiply());System.out.println(10 * 5 context.executeStrategy(10, 5));}执行结果从上面的例子我们简单总结下策略模式的优缺点1、优点策略模式提供了对“开闭原则”的完美支持用户可以在不修改原有系统的基础上选择算法或行为也可以灵活地增加新的算法或行为。策略模式提供了管理相关的算法族的办法。使用策略模式可以避免使用多重条件转移语句。2、缺点客户端必须知道所有的策略类并自行决定使用哪一个策略类。策略模式将造成产生很多策略类可以通过使用享元模式在一定程度上减少对象的数量。2 SPI 机制01 概念SPI 全称为 Service Provider Interface是一种服务发现机制。SPI 的本质是将接口实现类的全限定名配置在文件中并由服务加载器读取配置文件加载实现类。这样可以在运行时动态为接口替换实现类。正因此特性我们可以很容易的通过 SPI 机制为我们的程序提供拓展功能。02 Java SPI JDBC Driver在JDBC4.0 之前我们开发有连接数据库的时候通常先加载数据库相关的驱动然后再进行获取连接等的操作。// STEP 1: Register JDBC driverClass.forName(com.mysql.jdbc.Driver);// STEP 2: Open a connectionString url jdbc:xxxx://xxxx:xxxx/xxxx;Connection conn DriverManager.getConnection(url,username,password);JDBC4.0之后使用了 Java 的 SPI 扩展机制不再需要用 Class.forName(com.mysql.jdbc.Driver) 来加载驱动直接就可以获取 JDBC 连接。接下来我们来看看应用如何加载 MySQL JDBC 8.0.22 驱动首先 DriverManager类是驱动管理器也是驱动加载的入口。/*** Load the initial JDBC drivers by checking the System property* jdbc.properties and then use the {code ServiceLoader} mechanism*/static {loadInitialDrivers();println(JDBC DriverManager initialized);}在 Java 中static 块用于静态初始化它在类被加载到 Java 虚拟机中时执行。静态块会加载实例化驱动接下来我们看看loadInitialDrivers 方法。加载驱动代码包含四个步骤系统变量中获取有关驱动的定义。使用 SPI 来获取驱动的实现类字符串的形式。遍历使用 SPI 获取到的具体实现实例化各个实现类。根据第一步获取到的驱动列表来实例化具体实现类。我们重点关注 SPI 的用法首先看第二步使用 SPI 来获取驱动的实现类 , 对应的代码是ServiceLoader loadedDrivers ServiceLoader.load(Driver.class);这里没有去 META-INF/services目录下查找配置文件也没有加载具体实现类做的事情就是封装了我们的接口类型和类加载器并初始化了一个迭代器。接着看第三步遍历使用SPI获取到的具体实现实例化各个实现类对应的代码如下Iterator driversIterator loadedDrivers.iterator();//遍历所有的驱动实现while(driversIterator.hasNext()) {driversIterator.next();}在遍历的时候首先调用driversIterator.hasNext()方法这里会搜索 classpath 下以及 jar 包中所有的META-INF/services目录下的java.sql.Driver文件并找到文件中的实现类的名字此时并没有实例化具体的实现类。然后是调用driversIterator.next()方法此时就会根据驱动名字具体实例化各个实现类了现在驱动就被找到并实例化了。这里有一个小小的疑问 那么如果发现了多个 driver 的话要选择哪一个具体的实现呢那就是 JDBC URL 了driver 的实现有一个约定如果 driver 根据 JDBC URL 判断不是自己可以处理的连接就直接返回空DriverManager 就是基于这个约定直到找到第一个不返回 null 的连接为止。JDBC Driver 是 Java SPI 机制的一个非常经典的应用场景包含三个核心步骤定义 SPI 文件 指定 Driver class 全限定名 通过 DriverManager 静态类自动加载驱动 加载之后当需要获取连接时还需要根据 ConnectionUrl 判断使用哪一个加载完成的 Driver 。因此 JDBC Driver 的 SPI 机制是需要多个步骤配合来完成的 同时基于 Java SPI 机制的缺陷同样也无法按需加载。03 按需加载Dubbo SPI 机制基于 Java SPI 的缺陷无法支持按需加载接口实现类Dubbo 并未使用 Java SPI而是重新实现了一套功能更强的 SPI 机制。Dubbo SPI 的相关逻辑被封装在了 ExtensionLoader 类中通过 ExtensionLoader我们可以加载指定的实现类。Dubbo SPI 所需的配置文件需放置在 META-INF/dubbo 路径下配置内容如下optimusPrime org.apache.spi.OptimusPrimebumblebee org.apache.spi.Bumblebee与 Java SPI 实现类配置不同Dubbo SPI 是通过键值对的方式进行配置这样我们可以按需加载指定的实现类。另外在测试 Dubbo SPI 时需要在 Robot 接口上标注 SPI 注解。下面来演示 Dubbo SPI 的用法public class DubboSPITest {Testpublic void sayHello() throws Exception {ExtensionLoader extensionLoader ExtensionLoader.getExtensionLoader(Robot.class);Robot optimusPrime extensionLoader.getExtension(optimusPrime);optimusPrime.sayHello();Robot bumblebee extensionLoader.getExtension(bumblebee);bumblebee.sayHello();}}测试结果如下 另外Dubbo SPI 除了支持按需加载接口实现类还增加了 IOC 和 AOP 等特性 。SPI 机制的优势