前言
4 i3 c6 y9 K. ~0 C3 j4 B1 \: K 通俗的讲,适配器模式是将一个类的接口转换成客户希望的另外一个接口,在我们编写程序的时候,尤其是在我们使用到单片机做项目的时候,经常会用到。
但是往往我们做项目写程序的时候,并没有想到那么多,如果在不带操作系统的情况下,想要整个框架易于移植,易于理解,那么我们真的需要好好想想这个设计模式怎么写了。 下面我根据自己的项目经验,来说说适用于单片机的接口适配器模式的实现。大佬勿扰,多多指教。 一般实现 在我们做项目的时候,一般的实现,可能我们会这样写代码 - <font color="#001000"><font style="background-color:rgb(255, 255, 255)"><font face="Tahoma">! Q. G. Z3 h8 d9 t: D- j1 v# T
- // FileName: test.c. Z9 O: E1 B, S: j3 q8 K# l. \
- // 来源:公众号【技术让梦想更伟大】2 H$ Y. H- d$ d+ \4 u+ R
- #include <stdio.h>
* S; o9 d- g6 P; z) \ - #include “ExternModule.h”
/ G$ M2 g* |5 i6 k - $ S3 g$ ^- `4 E4 v8 R8 J+ X
- int main(void), q% g* u9 x/ S* u. y
- {3 f1 e5 c6 ]* }" w* a7 ]+ h/ f1 h
, L& |- |7 x9 J) w" D- /*初始化*/" f. m5 [2 Q0 \3 [9 a9 {
- vAllInit();8 Z; P4 V7 x( ~# X8 g! O
-
1 G; M& N+ c- W! E8 A; Q - while(1)
* _7 L, U; R7 m3 ]. t - {, ~0 _$ E1 r+ W6 l f/ R( ~
-
6 G6 C6 s9 u; V9 D* F2 k0 Y8 u - /*项目逻辑*/2 u, U. s. K" c/ g' X
- vLogicModule1();
7 ^2 j* M; M0 q0 o - 6 T- T0 \' G& Z5 k" @' `& L3 j- s
- vLogicModule2();
1 n# n7 e, }' `, C5 E4 j! R -
) D1 P t+ l4 M$ E$ A; v9 m# a - }9 l2 X( d! b$ B6 C
- }</font></font></font>3 A2 \# |) L2 p8 x( T' {2 I
复制代码1 t% h# H: d4 B
在其外部文件中,调用相对应的初始化函数以及逻辑函数,但是当我们项目很复杂的时候,逻辑关系也层层覆盖、交替的时候,这样的写法就有些不是很好看了。 接口适配器 首先我们还是要来定义数据结构,一般这样的项目分为这样几个步骤: $ X" C2 |5 p) ?. a* z
我们把这四个步骤封装起来,再定义数据结构如下: - <font color="#001000"><font style="background-color:rgb(255, 255, 255)"><font face="Tahoma">
3 X7 G3 M, J5 V( g7 Y6 } - // FileName: test1.c
" _" y% |! J) E0 n& L - // 来源:公众号【技术让梦想更伟大】
0 f6 W) _5 C; d4 F8 v# L - /* 适配器类型定义 */
0 K- U, {8 _9 a1 D/ E - struct _ADAPTER
9 V) v: i; u; A( ~ - {, Z$ r/ j3 x2 m
- void (*Init )( void ); //初始化函数/ R0 s/ \0 c; k
- void (*Input )( void ); //输入转换函数' Z( m: V7 F9 G; O" L7 ^
- void (*Process )( void ); //处理函数# G; A e- E0 [8 b
- void (*Output )( void ); //输出转换函数
/ _) z: C6 {+ {# F1 A5 r - };; g3 _- D% I7 _
- typedef struct _ADAPTER ADAPTER ;</font></font></font>; m: w* y" t1 d3 Y
复制代码5 P' B) C# s0 W
那么初始化函数,我们先来这样定义
5 c3 M, c$ B' R& f( S. q, A6 m. X% k- // FileName: test1.c, R8 M) @7 y# G. k
- // 来源:公众号【技术让梦想更伟大】7 d+ }+ Y4 `/ \4 d) P
- /* 模块初始化 */
# \& m* h l" o9 j5 q- o! c - void moduleInit( ADAPTER *module )
$ T, x/ h: h6 k& W) s J - {
' V" `0 }4 q! R) u6 D, t9 M* C" S9 f" W: c - if( module->Init != NULL )
' A3 Q2 O3 F, Q$ O3 @/ ~; d - {/ D! F. M. B- m. I& ]! T$ e
- module->Init();
- [3 g5 d6 n9 l; n - }( K4 }" h7 v3 _. V, ^) @: O
- }
复制代码6 b X! C$ \ s3 L# C
模块的逻辑运行,我们可以这样使用 - <font color="#001000"><font style="background-color:rgb(255, 255, 255)"><font face="Tahoma">
. G+ W/ o7 R9 j& T - // FileName: test1.c7 Q! _( |0 d0 Y4 M$ ~# E
- // 来源:公众号【技术让梦想更伟大】
0 c% s( H) D. ^" w- l! Z0 Y - /* 模块逻辑运行 */
) E' G/ O" Y( z, o$ X! c5 M9 S9 a - void moduleRun( ADAPTER *module )
: @# p* V" P; a - {: A% _; k# d- _% K4 a2 u
- // 模块输入适配接口不为空,则执行输入适配操作
9 V) h D- @2 |9 C# y' J9 c - if( module->Input != NULL )4 _$ Z. j' q x/ U; [- e& s
- {7 O5 c0 B; E. A: H
- module->Input();
1 f' w( c2 X" K* h' e1 G - }# j q( c! z7 Z; C5 e0 D3 k
5 p) x E! S8 j- // 模块处理接口不为空,则执行处理操作
+ s0 y: R0 K. i* ^' I* ~ - : S* e! t4 r$ g; q/ T
- // 模块输出适配接口不为空,则执行输出适配操作
( J) X% P# _; l0 w) J - }</font></font></font># j1 V2 ]- n/ Y1 H
复制代码
5 |0 i, k% R; Q
在定好了这些数据结构以及封装之后,我们在每个子模块中都只需要调用这个模式即可。例如有一个需求,需要点一个灯,我们建立独立文件,在文件中申明 - $ r+ |6 Q: f( u
- // FileName: led.c
' Z& G/ d! o8 f - // 来源:公众号【技术让梦想更伟大】
- m9 e1 b7 T; Y. w0 B - /*led灯运行 */& u0 ?7 a0 k3 e1 g1 ~
- ADAPTER LedModule = { vLedInit, NULL, vLedRunModule, NULL };
复制代码& f2 h7 e1 {5 k- d) Y1 }
那么接下来只需要对初始化函数,逻辑运行函数进行描述就可以了。同理,我们需要一个按键的功能,在另一个独立文件申请
: g. |! M/ B) }- // FileName: key.c
/ Z9 r( r9 ], l( d( s! d - // 来源:公众号【技术让梦想更伟大】, l H* A" [+ T; t9 \/ g
- /*按键运行 */
( Y, L) m3 W. J: m - ADAPTER KeyModule = { vKeyInit, NULL, vKeyRunModule, NULL };
复制代码! V1 |) [* {: _0 F9 t/ H2 J: y3 u
这样的话就便于我们拆分需求,便于移植,同时程序也就模块化了,最后我们在main文件中做的就是调用这些函数就行。我们需要这样做。 - 5 H& p, e; \2 g$ \* k$ ^) ?# s
- // FileName: main.c" d# ?9 z2 Q. G9 [- X
- // 来源:公众号【技术让梦想更伟大】
% ~" x/ I7 y4 ?& | G* r% r - /*主函数 */8 G4 ?2 P1 t6 C% d" ^6 c' D
- void main( void )! I& I9 h2 }. J0 _1 C
- {
9 v/ G8 h B- }
" J$ l* b' K1 W; Y6 {! Y- moduleInit( &LedModule );
9 c4 v4 o! i$ Y# H+ V( T - moduleInit( &keyModule );! W+ Y/ I5 C; c, U' {" Y. p
-
5 H; R. W* S/ G# r% k# z# m - while( 1 )
) g' G( K: x& H - {9 a( x2 p$ B- b' ?
- moduleRun( &LedModule );
( b0 z1 Q4 w" O - moduleRun( &keyModule );
4 B. l4 u% G3 C# D6 a3 Q/ H$ e - }+ \: e# N% D! o- {% z7 a; S- _
-
0 f( _) ?3 i0 y - }
复制代码 : l: G, {: q5 g
最后 main函数就是这么简单了,整个架构也是很清晰,体现出编程之美。 |