Adapter 패턴 - 1

남이 작성한 코드를 내 코드에 적용해야 할 때가 아주 많습니다. 그러나 대부분 크기가 다른 볼트와 너트처럼 딱 맞아 떨어지지 않습니다. 이럴 땐 어떻게 해야 할까요? 중간에 양 쪽에 잘 맞는 나사를 하나 덧 대는 것으로 해결 할 수 있습니다.

 

Adapter 패턴은 흔히 레거시 코드(Legacy Code)라고 불리는 예전에 작성된 코드들을 현재의 코드와 맞게 고치는 방법입니다. 다른 사람이 작성한 코드를 자신의 코드에 맞게 고쳐쓰는 방법으로도 좋습니다.

 

우리는 중간에 Adapter라는 Wrapper 함수를 만들어 Adapter패턴을 구현할 것입니다. 이번 예제에서는 display라는 콘크리트 코드를 driver라는 interface와 호환이 되도록 만들어 보겠습니다. 우선 display 콘크리트 코드부터 보도록 하겠습니다. 원시 코드의 구조를 먼저 파악하고 맞춰야 할 부분을 찾는 것이 좋습니다.

 

display.h 부터 보도록 하겠습니다. display의 init, deint, read, draw 주요 함수들을 포함한 구조체가 먼저 선언되어 있습니다.

typedef struct
{
	bool (*init)(void);
	bool (*deinit)(void);
	bool (*read)(uint32_t addr, uint8_t *buffer, uint16_t len);
	bool (*draw)(uint16_t x, uint16_t y, uint8_t *buffer, uint16_t len);
}display_t;

extern display_t *setup_display(void);
 

setup_display로 부터 구조체의 포인터를 얻어와 display를 구동시키는 아주 기본적인 구조입니다. 딱히 나쁘다라고 볼 수 없는 구조입니다.

 

 

이번엔 display.c 코드를 보도록 하겠습니다. 구조체의 선언된 함수포인터들의 본체가 구현되어 있습니다.

static bool init(void);
static bool deinit(void);
static bool read(uint32_t addr, uint8_t *buffer, uint16_t len);
static bool draw(uint16_t x, uint16_t y, uint8_t *buffer, uint16_t len);

display_t this = 
{
	init,
	deinit,
	read,
	draw
};

display_t *setup_display(void)
{
	this->init();
	return &this;
}

static bool init(void)
{
	//need to implement
	return true;
}

static bool deinit(void)
{
	//need to implement
	return true;
}

static bool read(uint32_t addr, uint8_t *buffer, uint16_t len)
{
	//need to implement
	return true;
}

static bool draw(uint16_t x, uint16_t y, uint8_t *buffer, uint16_t len)
{
	//need to implement
	return true;
}
 

26번줄에 setup_display를 하면 init을 하고 포인터를 돌려주게 되어있으나 필요하지 않는 경에에는 init을 빼도 됩니다. 딱히 흠 잡을 데는 없지만 그렇다고 특별하지도 않은 코드입니다.

 

그런데 궁극적으로 왜 바꾸려고 할까요? 만약 어떠한 임베디드 시스템에 여러가지 device들이 붙는 다면 예를 들어 LCD, Volume IC, Codec IC, Uart 등입니다. 각각의 device들이 위와 같이 하나씩 콘크리트 코드를 가지고 있다면 코드가 상당히 복잡해 집니다. 복잡하다는 것은 버그가 내재될 확율이 높으며 디버깅을 어럽게 합니다.

 

어느 device는 write로, 다른 device는 draw로 각각의 device들의 원시 코드를 열어봐야 정확히 에러를 내지 않고 코드를 완성할 수 밖에 없습니다. 이러한 복잡성을 줄이고 코드의 추측으로 그 사용법을 알도록, 그리고 일률적인 코드 확장을 위해 콘크리트 코드들이 device의 driver라는 공통의 interface를 구현하게 하면 됩니다.

 

문제는 이번 예전의 콘크리트 코드가 이미 상당히 달라져 구현되어 있다는 것입니다. 그래서 우리는 앞으로 구현될 driver interface에 display 콘크리트 코드를 맞출 예정입니다.

 

다음장에서 driver interface를 구현해 보도록 하겠습니다.

 

'▶ C Application > 디자인 패턴' 카테고리의 다른 글

Adapter 패턴 - 3  (0) 2023.12.24
Adapter 패턴 - 2  (0) 2023.12.24
Factory method 패턴  (0) 2023.12.23
소프트웨어 Timer 만들기  (0) 2023.12.20
Template method 패턴  (0) 2023.12.17