操屁眼的视频在线免费看,日本在线综合一区二区,久久在线观看免费视频,欧美日韩精品久久综

新聞資訊

    一、背景

    責任鏈模式(Chain of )為請求創建了一個接收者對象的鏈。這種模式給予請求的類型,對請求的發送者和接收者進行解耦。這種類型的設計模式屬于行為型模式。

    觀察者模式( ),則是當一個對象被修改時,則會自動通知依賴它的對象。觀察者模式屬于行為型模式。

    為什么把這兩種模式放一起?是因為這兩者在C語言里的實現比較接近,責任鏈是在接收到請求時,分別給接收對象進行處理,當處理的請求不是自身接收對象的請求時(或者是自身的責任范圍內的請求,具體視責任鏈的定義來決定),則傳遞給下一個接收對象。所以對于責任鏈來說,只有在職責范圍內的請求才會執行。而觀察者模式,則是不管職責范圍,全體都會執行。所以觀察者模式可以看作是責任鏈的一種特殊情況(即所有條件均滿足的情況)。

    二、名詞釋義

    既然提到鏈,那這里肯定會涉及鏈表c實現觀察者模式,所以這里其實是兩部分的內容,一個是責任的劃分,一個是鏈表的表示。而對于觀察者,則是少了一個責任劃分的條件而已。

    三、C語言例子 責任鏈

    比如現在要做一個手機轉賬的功能,需求是當轉賬金額不大于100時,直接轉,不需要任何提示;當轉賬金額大于100時,提示確認信息;當轉賬金額大于1000時,需要密碼確認;當轉賬金額大于10000時,需要手機短信驗證碼確認。比如當轉賬金額為20000時,需要提示信息,并且密碼確認,并且還需要手機短信驗證。

    我們先用常規思路來解答一下。

    /* 無動作 */
    extern void DoNothing(void);
    /* 提示 */
    extern void Tips(void);
    /* 密碼確認 */
    extern void PswConfig(void);
    /* 驗證碼確認 */
    extern void CodeConfig(void);
    void TransferFunc(uint32_t value)
    {
    	if (value >= 10000)
    	{
    		CodeConfig();
    	}
    	else if (value >= 1000)
    	{
    		PswConfig();
    	}
    	else if (value >= 100)
    	{
    		Tips();
    	}
    	else
    	{
    		DoNothing();
    	}
    }
    

    上面這種實現其實沒什么問題,但如果后面要加個操作,比如金額大于10w時,需要本人視頻核對。那這個時候就需要去改動這個函數主體內容,一不小心可能還會把原本那些金額的處理給變更成其他操作。為了讓執行邏輯與變更對象解耦開,這里使用責任鏈的方式。

    /* 定義責任鏈的結構 */
    struct tagTransfer
    {
    	uint32_t Value;
    	void (*Func)(void);
    	struct tagTransfer *Next;
    };
    /* 無動作 */
    

    編程語言實現模式_c實現觀察者模式_c語言實現策略模式

    extern void DoNothing(void); /* 提示 */ extern void Tips(void); /* 密碼確認 */ extern void PswConfig(void); /* 驗證碼確認 */ extern void CodeConfig(void); /* 定義鏈頭 */ struct tagTransfer *Head = NULL; void TransferAddList(uint32_t value, void (*func)(void)) { struct tagTransfer *last = Head; struct tagTransfer *next = malloc(sizeof(struct tagTransfer)); if (NULL != next) { next->value = value; next->func = func; /* 按責任等級排個序 */ if (NULL == last) { last = next; } else { for (;NULL != last->next; last = last->next) { /* 按從大到小排序 */ if (value > last->next->value) { next->next = last->next; last->next = next; return ; } } last->next = next; } } } /* 責任鏈執行判斷 */ void TransferFunc(uint32_t value) { struct tagTransfer *last = Head; for (;NULL != last; last = last->next) { if (value > last->value)

    c實現觀察者模式_編程語言實現模式_c語言實現策略模式

    { last->func(); } else { break; } } }

    但對于嵌入式端,沒必要使用動態鏈接的形式增減責任鏈內容c實現觀察者模式,這里有另一種更適用于嵌入式的靜態鏈接,沒錯,就是我們的老朋友表驅動。下面用表驅動的例程來展示下。

    /* 定義責任鏈的結構 */
    struct tagTransfer
    {
    	uint32_t Value;
    	void (*Func)(void);
    };
    /* 無動作 */
    extern void DoNothing(void);
    /* 提示 */
    extern void Tips(void);
    /* 密碼確認 */
    extern void PswConfig(void);
    /* 驗證碼確認 */
    extern void CodeConfig(void);
    /* 做好責任劃分的靜態定義 */
    static const struct tagTransfer FuncTable[] =
    {
    	{0, DoNothing},
    	{100, Tips},
    	{1000, PswConfig},
    	{10000, CodeConfig},
    };
    /* 責任鏈執行判斷 */
    void TransferFunc(uint32_t value)
    {
    	for (uint8_t i = 0; i < sizeof(FuncTable) / sizeof(FuncTable[0]); i++)
    	{
    		if (value >= FuncTable[i].Value)
    		{
    			FuncTable[i].Func();
    		}
    	}
    }
    

    觀察者

    編程語言實現模式_c語言實現策略模式_c實現觀察者模式

    對于觀察者模式,可以使用同樣的結構,只是使用的場景不大一樣,一般需要訂閱、通知的場景,就像公眾號,只要訂閱了公眾號,當公眾號有新的推文時,會直接通知到所有訂閱這個公眾號的人。當前技術中,有使用這種方式的,比較典型的,就是MQTT協議。

    這里我們也來做個小例子,比如現在有個觸摸屏,當點擊屏幕的按鍵時,需要顯示按鍵被按下的狀態,另外還需要響一下蜂鳴器。那我們先用常規思路處理一下。

    /* 按鍵狀態 */
    enum emKeyState
    {
    	KEY_STA_bounce = 0,		/* 按鍵彈起 */
    	KEY_STA_press = 1,		/* 按鍵按下 */
    };
    extern uint8_t KeySta = KEY_STA_bounce;
    /* 蜂鳴器動作 */
    extern void BuzzerFunc(void);
    /* 顯示屏刷新 */
    extern void DisplayFunc(void);
    void main(void)
    {
    	while(1)
    	{
    		/* 按鍵按下時動作 */
    		if (KEY_STA_press == KeySta)
    		{
    			/* 蜂鳴器響 */
    			BuzzerFunc();
    	
    			/* 界面刷新 */
    			DisplayFunc();
    		}
    	}
    }
    

    如果這時候需要再執行一個點亮LED的動作,那就需要找到按鍵按下這個判斷條件,增加一個點亮LED的動作。

    /* 按鍵狀態 */
    enum emKeyState
    {
    	KEY_STA_bounce = 0,		/* 按鍵彈起 */
    	KEY_STA_press = 1,		/* 按鍵按下 */
    };
    extern uint8_t KeySta = KEY_STA_bounce;
    /* 蜂鳴器動作 */
    extern void BuzzerFunc(void);
    /* 顯示屏刷新 */
    extern void DisplayFunc(void);
    

    c實現觀察者模式_編程語言實現模式_c語言實現策略模式

    /* 點亮LED燈 */ extern void LEDFunc(void); void main(void) { while(1) { /* 按鍵按下時動作 */ if (KEY_STA_press == KeySta) { /* 蜂鳴器響 */ BuzzerFunc(); /* 界面刷新 */ DisplayFunc(); /* 點亮LED燈 */ LEDFunc(); } } }

    上面這種寫法有問題么?實現起來沒問題,也添加功能也很方便,但是有個問題,就是如果現在想把按鍵的功能封裝起來放一個模塊里,這時候按鍵觸發的執行動作應該怎么處理?總不能把功能也封裝進去,那以后每加一個功能就得改一次模塊。所以這里就要用到觀察者模式了。

    這里的按鍵按下,可以看作是一個事件,當觸發這個事件時,需要執行蜂鳴器響、界面刷新、點亮LED燈等操作。其實就是當發生了按鍵按下的事件時,需要同步通知蜂鳴器、界面和LED同步動作。這個模式在嵌入式里其實就是一個回調函數的應用。下面我們來看下怎么實現。

    /*************************按鍵模塊的實現.c****************************/
    /* 按鍵狀態 */
    enum emKeyState
    {
    	KEY_STA_bounce = 0,		/* 按鍵彈起 */
    	KEY_STA_press = 1,		/* 按鍵按下 */
    };
    /* 觀察者鏈表結構 */
    struct tagKeyFunc
    {
    	void (*Func)(void);
    	struct tagKeyFunc *Next;
    };
    struct tagKeyFunc *Head;
    uint8_t KeySta = KEY_STA_bounce;
    /* 回調函數注冊 */
    void KeyPress_AddFunc(void(*func)(void))
    {
    	struct tagKeyFunc *last = Head;
    	/* 新注冊的功能插入鏈尾 */
    	for (; NULL != last; last = last->Next);
    

    c實現觀察者模式_c語言實現策略模式_編程語言實現模式

    last->Func = func; } /* 事件觸發時執行注冊的回調函數 */ void KeyEventFunc(void) { struct tagKeyFunc *last = Head; /* 按鍵按下時,執行所有注冊的功能 */ if (KEY_STA_press == KeySta) { for (; NULL != last; last = last->Next) { last->Func(); } } } /********************************************************************/ /***************************應用.c*********************************/ extern void KeyPress_AddFunc(void(*func)(void)); extern void KeyEventFunc(void); /* 蜂鳴器動作 */ extern void BuzzerFunc(void); /* 顯示屏刷新 */ extern void DisplayFunc(void); /* 點亮LED燈 */ extern void LEDFunc(void); void main(void) { /* 按鍵觸發功能注冊 */ KeyPress_AddFunc(BuzzerFunc); KeyPress_AddFunc(DisplayFunc); KeyPress_AddFunc(LEDFunc); while(1) { KeyEventFunc(); } } /********************************************************************/

    四、適用范圍

    責任鏈,適用于不同操作對象各自有明確的職責劃分。

    觀察者,適用于需要遍歷通知的場景。

    五、優劣勢 兩者都有一個比較明顯的優勢,就是把觸發事件和執行功能兩者解耦開。如果使用鏈式結構,可以很方便地進行動態添加和刪除。 功能執行的位置比較有局限性,不靈活,比如上面例子,所有功能只能在按鍵按下時才能執行,如果需要在彈起時執行則不能實現,需要另外增加一個彈起執行的回調,也就是功能執行的位置完全取決于事件開放的位置。使用回調時,不容易發現無限遞歸的情況,即使用時有A回調B,B回調A這種無限調用的風險。

網站首頁   |    關于我們   |    公司新聞   |    產品方案   |    用戶案例   |    售后服務   |    合作伙伴   |    人才招聘   |   

友情鏈接: 餐飲加盟

地址:北京市海淀區    電話:010-     郵箱:@126.com

備案號:冀ICP備2024067069號-3 北京科技有限公司版權所有