言語Design Pattern-Observer Pattern

3109 ワード

Observerモードは一般的な符号化モードである.
Observerモードの使用は非常に簡単です.プライマリ・プロセスはobserverを作成し、使用するライブラリまたはAPIに登録します.その後、適切なイベントが発生した場合、登録したObserverにメッセージまたはデータを送信できます.したがって、プライマリ・プロセッサは、自分のすべきことをしてobserverに送信されるたびに処理するだけです.
観察者モードを用いて,湿度を測定することによってユーザ(主関数)に通知する定期的に湿度を測定するセンサを作成する.
//humidity.h 
#ifndef OBSERVER_HUMIDITY_H_
#define OBSERVER_HUMIDITY_H_

typedef void (*observer_hanlder_t)(uint32_t humi);
bool register_observer(observer_handler_t observer);
bool unregister_observer(observer_hanlder_t observer);
void calculation_humidity(void);
#endif 

//humidity.c 
#define MAX_OBSERVER_COUNT 20
static oberver_handler_t observer_handler[MAX_OBSERVER_COUNT];
static uint8_t observer_handler_len = 0;

bool register_observer(observer_handler_t observer)
{
	if(observer_handler_len >= MAX_OBSERVER_COUNT)
    {
    	return FALSE;
    }
    for(uint8_t observer_cnt = 0; observer_cnt < MAX_OVSERVER_COUNT, observer_cnt++)
    {
    	if(observer_handler[observer_cnt] == observer)
        {
        	return FALSE;
        }
    }
    observer_hanlder[observer_handler_len++] = observer;
    return TRUE;
}

bool unregister_observer(observer_hanlder_t observer)
{
	for(uint8_t observer_cnt = 0; observer_cnt < observer_handler_len; observer_cnt++)
    {
    	if(observer_handler[observer_cnt] == observer)
        {
        	for(uint8_t cnt_temp = observer_cnt; cnt_temp < observer_handler_len; cnt_temp++)
            {
            	if((cnt_temp - 1) == observer_len)
                {
                	break;
                }
                observer_hanlder[cnt_temp] = observer_handler[cnt_temp -1];
            }
            observer_hanlder_len--;
            return TRUE;
        }
    }
    return FALSE;
}

static void update_observer(uint32_t humi)
{
	for(uint8_t observer_cnt = 0; observer_cnt < observer_handler_len; observer_cnt++)
    {
    	observer_handler[observer_cnt](humi);
    }
}

void calculate_humidity(void)
{
	uint32_t humi = 0;
    //습도 계산 
    update_observer (humi);
}

上のコードを見てみましょう.
まず,MAX OBSERVER COUNTは関数ポインタ配列に設定され,最大20個のobserver登録が可能である.
register observer関数でobserverが登録されている場合、observerにobserverが登録されている場合、FALSEが返されます.
登録されているobserverはunregister observer関数でハッシュできます.データ構造observer hanlder配列に対応するobserverがある場合は、配列を削除し、後ろの配列を前に押し出します.
湿度はcalculate he湿度関数で計算し、受信した湿度値をupdate observerで登録したobserverに通知します.
(通常、湿度センサadcインタフェースまたはtimerによってcalculate湿度関数が呼び出され、ユーザの必要に応じてこの関数が呼び出されて計算される.)
今main関数から見ると
static void display_humidity_hanlder(uint32_t humidity);
static void file_write_humidty_handler(uint32_t humidity);

void main(void)
{
	register_observer(display_humidty_handler);
    register_observer(file_write_humidity_handler);
    
    while(1)
    {
    	calculate_humidty();
        delay_ms(1000);
    }
}
static void display_humidity_hanlder(uint32_t humidity)
{
	//TODO : 습도 화면 표시 작성
}
static void file_write_humidty_handler(uint32_t humidity)
{
	//TODO : 습도 파일 저장 작성 
}
main関数に2つのobserverを登録します.次に、while文で湿度センサ値を計算し、登録した観察者に結果を伝えます.結果観察者は、それぞれのロールに従ってタスクを処理します.