1. 程式人生 > >用查表法代替switch-case

用查表法代替switch-case

更加符合close-open原則,即對修改封閉,對擴充套件開放,增加程式碼的穩定性及可維護性。

以Windows的訊息處理函式為例,典型的Win32 API程式中這樣處理訊息:
LRESULT CALLBACK WindowProc(HWND hwnd,
    UINT uMsg,
    WPARAM wParam,
    LPARAM lParam
)
{
    LRESULT lResult = 0;
    switch(uMsg)
    {
    case WM_SIZE:
         lResult = OnSize(wParam, lParam);
         break;
    case WM_SHOWWINDOW:

         lResult = OnShow(wParam, lParam);
         break;
    case WM_PAINT:
         lResult = OnPaint(wParam, lParam);
         break;
    default:
         lResult = DefWindowProc(hwnd, uMsg, wParam, lParam);
         break;
    }
    return lResult;
}

LRESULT OnSize(WMPARAM, LPARAM){...}
LRESULT OnShow(WMPARAM, LPARAM){...}

LRESULT OnPaint(WMPARAM, LPARAM){...}
以上程式碼整齊而清新,基本上沒有什麼毛病。但很顯然每加一個訊息,都需要修改WindowProc中的case語句塊,尤其是當case非常多的情況下,找到case的尾部並非一件容易的事情。如果情況更糟一點,case中的程式碼並非上面演示的如此整潔,正確新增一個case並非易事,而且如果在case後忘了break,後果則可能是無法預料的。要知道每次修改都是一次冒險,這也是要求程式碼對修改封閉這一設計原則的來由。更好的程式碼:
struct MessageMapEntry
{
    UINT uMsg;
    LRESULT (*handler)(WPARAM, LPARAM);

};
MessageMapEntry MessageMap[] =
{
    {WM_SIZE, OnSize},
    {WM_SHOWWINDOW, OnShow},
    {WM_PAINT, OnPaint},
};
LRESULT CALLBACK WindowProc(HWND hwnd,
    UINT uMsg,
    WPARAM wParam,
    LPARAM lParam
)
{
    for(int i=0; i<sizeof(MessageMap)/sizeof(MessageMap[0]); ++i)
    {
        if(MessageMap[i].uMsg == uMsg)
        {
            return MessageMap[i].handler(wParam, lParam);
        }
    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
比較這兩段程式碼,後者的邏輯程式碼僅8行,且不再隨case的增加而增加,也就是說WindowProc這個函式對於修改已經封閉了。而每一個case只要在MessageMap陣列中新增一個條目,所以對擴充套件是開放的。單從程式碼數量來說,一個case需要至少3行,而一個表目只需要1行,更少的程式碼行意味著更少的維護工作量,也意味著更小的出錯概率。

另外,採用表驅動設計,可以促進模組化設計,因為它強制要求將每個表目的處理提取為獨立的函式,而不是像switch-case一樣允許將處理程式碼塊直接嵌入case語句中。

MFC正是採用類似的表驅動設計來處理視窗訊息,從而達到非常好的模組獨立性和可擴充套件性,且處理效率方面也絲毫沒有受影響。

相關推薦

代替switch-case

更加符合close-open原則,即對修改封閉,對擴充套件開放,增加程式碼的穩定性及可維護性。以Windows的訊息處理函式為例,典型的Win32 API程式中這樣處理訊息:LRESULT CALLBACK WindowProc(HWND hwnd,    UINT uMs

JAVA-初步認識-第五章-數組-練習

得到 font 設置 來看 num 限制 day 返回值 自己 一. 查表法是一種思想,是一種生活中都會存在的操作。 查表法的特征在於:有對應關系。對應關系的一方上是有序的編號。如果有序的編號不從0開始,重新設置角標即可。 星期就可以使用查表法,星期一是monday,

解決calendar中月份及星期初始值為0的情況。

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco } p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #3933ff } p.p3 { margin:

氣泡排序,二分

** java氣泡排序 public static void main(String[] args) { int x = 45; int[] arr = {12,3,33,58,36,223,24,41,5,45,36}; for(int i=0;i<arr.len

Java第五天學習筆記~陣列(最值,遍歷,排序,等)

定義格式 int[ ] arr=new int [3]{89,78,67,14}; int[ ]arr={89,78,67,14}; 對陣列最基本的操作就是存和取 遍歷 int[] arr={89,34,270,18}; for(int x=0;x<arr.length;x

Python 實現簡單的 switch/case 語句

在Python中是沒有Switch / Case語句的,很多人認為這種語句不夠優雅靈活,在Python中用字典來處理多條件匹配問題字典會更簡單高效,對於有一定經驗的Python玩家不得不承認,的確如此。 但今天我們還是來看看如果一定要用Python來Switch /

《PT100(0.1分度)》------------李偉龍

92.1992    92.2384    92.2776    92.3168    92.356    92.3952    92.4344    92.4736    92.5128    92.552 //-19.9 ---- -19 92.5912    92.63

qt實現crc16

#ifndef COMMON_H#define COMMON_H#include <QString>#include <QByteArray>const quint8 chCRCHTalbe[] =                           

Modbus CRC16校驗演算法--(已經過本人測試,工作良好)

程式碼如下: uchar auchCRCHi[]= { 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0

CRC——的由來及Java實現CRC8校驗演算法

你也可以檢視我的其他同類文章,也會讓你有一定的收貨! 大概思路 我先說一下查表法,表的計算方法,以CRC4為例: 生成多項式:B = 10011B 測試資料:A = 0011 1110B 1、查表法實際上是利用XOR的交換律和結合律:(A X

CRC32校驗演算法C語言版()

最近用到CRC校驗演算法,就找了些資料,學習了一下,網上關於CRC32的資料也多,但感覺不是很完整,或者太高深。 CRC演算法查表法很常見,但表是怎麼來的,有些資料說得不很清楚。 我來說一下我的看法:

OpenCV中的LUT函式(

簡單來說就是通過對映關係,將原影象的畫素值進行縮減操作,比如說  table[56]=5,就表示將畫素值為56的點對映為5,這種方法僅有賦值運算,不涉及乘除、加減運算,可以極大降低時間複雜度。程式原始碼:/* LUT查表函式的使用,結合滑動條函式 */ #include

空間換時間,的經典例子

## 前言 上一篇分享了:[C語言精華知識:表驅動法程式設計實踐](https://t.1yb.co/rcS) 這一篇再分享一個查表法經典的例子。 我們怎麼衡量一個函式/程式碼塊/演算法的優劣呢?這需要從多個角度看待。本篇筆記我們先不考慮程式碼可讀性、規範性、可移植性那些角度。 在我們嵌入式中,我們需

陣列代替if-else和switch-case語句

       表驅動法(Table-Driven Approach),通過在表中查詢資訊,來代替很多複雜的if-else或者switch-case邏輯判斷。這是一種設計的技巧,可以應用很多的場合,不僅可以提高程式的效能,也能大大減少程式碼量,使得程式碼變得高效和優雅。下面將

SQL語句

bsp from eache http src com 查表 舉例 語句 (計應154蘭家才)格式 舉例 select 教師編號,教師職稱 from dbo.Teacher 用SQL語句查表

排序算復雜度速

排序 table borde apt 長度 d+ itl ont 時間復雜度 各種常用排序算法 類別 排序方法 時間復雜度 空間復雜度 穩定性 平均情況 最好情況 最壞情況 輔助存儲 插入排序 直接插入 O(n2) O

頭插合並單鏈

void print clu b- 合並單鏈表 truct tdi pre log 1 #include<stdio.h> 2 #include<stdlib.h> 3 typedef struct Node 4 { 5 int

判定測試例設計

info bsp 機器 inf 多條 就是 size pan -s 判定表也稱我決策表,能表示輸入條件的組合,以及與每一輸入組合對應的動作組合。與因果圖法相似判定表法主要側重輸入條件之間的邏輯關系。 1.判定表主要包含以下五部分: 條件樁:列出所有可能的條件 條件項:列出

日常學習隨筆-的形式實現普通二叉樹的新增、找、遍歷(前、中、後序)等基礎功能(側重源碼+說明)

新增 rabl super 例子 信息 count TP title 處理 一、二叉樹 1、二叉樹的概念 二叉樹是每個節點最多有兩個子樹的樹結構。通常子樹被稱作“左子樹”(left subtree)和“右子樹”(right subtree),其次序不能任意顛倒。 2、性質

python字典實現switch..case類似的函數調

python info 調試 turn return 字典 elif 實現 不同 python中沒有swich..case,若要實現一樣的功能,又不想用if..elif來實現,可以充分利用字典進行實現 主要是想要通過不同的key調用不同的方法,在學習過程中,發現不管輸入的k