Adapter 패턴 - 3

지난 시간에 이어 display - driver를 잇는 adapter 부분을 구현해 보도록 하겠습니다. 궁극적으로는 아래와 같은 구조가 될 것입니다.

 

display → adapter → driver

 

결국 adapter 패턴이 있어 display도 다른 driver처럼 사용할 수 있게 됩니다. 먼저 adapter의 header(interface) 부터 살펴 보도록 하겠습니다.

extern driver_t *setup_display_adapter(void);
 

setup_display_adapter을 extern으로 선언해줍니다. setup_display_adapter를 호출하면 driver_t의 포인터를 전달해 주도록 되어있습니다.

 

헤더를 선언할 때 아래와 같은 코드가 많이 나오는데요, 혹시 모르시는 분들이 계실까봐 설명드리자면 여러 파일에서 하나의 header파일을 include할 때 중복선언으로 컴파일러가 에러를 내게 됩니다. 그럴 경우 아래와 같이 define 해주면 에러를 나지 않게 됩니다.

 

#ifndef ADAPTER_ADAPTER_H_

#define ADAPTER_ADAPTER_H_

...(생략)

#endif /* ADAPTER_ADAPTER_H_ */

 

계속해서 .c 파일을 보도록 하겠습니다. display와 driver의 호환을 위해 driver의 각 메소드들을 구현하고 있습니다.

static bool open(void);
static bool close(void);
static bool read(uint32_t addr, uint8_t *value);
static bool write(uint32_t addr, uint8_t *value, uint32_t len);

static display_t *display=null;
static driver_t *this = 
{
	DRIVER_ID_DISPLAY,
	open,
	close,
	read,
	write
};

driver_t *setup_display_adapter(void)
{
	display = setup_display();
	return &this;
}


static bool open(void)
{
	if(display == null)
		return false;

	return display->init();
}

static bool close(void)
{
	if(display == null)
		return false;

	return display->deinit();
}

static bool read(uint32_t addr, uint8_t *value, uint32_t len)
{
	if(display == null)
		return false;

	return display->read(addr, value, (uint16_t) len);
}

static bool write(uint32_t addr, uint8_t *value, uint32_t len)
{
	if(display == null)
		return false;

	return display->draw((uint8_t)(addr >> 8), (uint8_t)(addr&0x00FF), value, len);
}
 

driver의 write를 display의 draw로 구현한 부분을 보시면 감이 촥하고 오실 겁니다. driver의 address를 display의 x, y 좌표로 변경하였습니다.

 

내부적으로 display를 이용해 처리하고 외부적으로는 driver_t를 전달해줘서 다른 driver와 동일한 취급을 받도록 하고있습니다. 이것이 wrapper입니다.

 

그럼 이제 main.c에서 사용하는 예제를 보도록 하겠습니다.

void main(void)
{
	set_driver(setup_display_adapter());
	get_driver(DRIVER_ID_DISPLAY)->open();

	static uint8_t buffer[100];
	static uint8_t color = 0;

	while(1)
	{
		color++;

		for(int i=0; i<100; i++)
		{
			buffer[i] = color;
		}

		get_driver(DRIVER_ID_DISPLAY)->write(0x0000, buffer, 100);
		delay_ms(1000);
	}
}
 

setup_display_adapter호출하여 driver를 넘겨주고, 다른 driver와 동일한 방식으로 사용하는 것을 볼 수 있습니다.

 

위의 예제에서는 x=0, y=0 좌표에 color값을 바꿔가며 1초에 한번씩 화면을 갱신하는 루틴을 구현해 놓고 있습니다.

 

아쉽게도 위의 코드에서 약간 위험해 보는 부분이 보이네요. 바로 3번째 줄에서 setup_display_adapter 와 16번줄의 DRIVER_ID_DISPLAY가 어떠한 연관이 있는지 모르면 사용할 수가 없게 되는데, 이러한 사항이 문제가 될 수 있습니다.

 

여러분들이 직접 어떻게 하면 이 문제를 풀 수 있을지 고민해 보는 것도 좋을 거 같습니다.

 

좋은 하루되세요!

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

Facade 패턴  (0) 2024.02.12
Builder 패턴 - 키(Key)처리  (1) 2024.01.17
Adapter 패턴 - 2  (0) 2023.12.24
Adapter 패턴 - 1  (0) 2023.12.24
Factory method 패턴  (0) 2023.12.23