日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當前位置:首頁 > > 嵌入式大雜燴
[導(dǎo)讀]GOF的《設(shè)計模式》一書的副標題叫做“可復(fù)用面向?qū)ο筌浖幕A(chǔ)”,從標題就能看出面向?qū)ο笫窃O(shè)計模式基本思想。


前言

GOF的《設(shè)計模式》一書的副標題叫做“可復(fù)用面向?qū)ο筌浖幕A(chǔ)”,從標題就能看出面向?qū)ο笫窃O(shè)計模式基本思想。

由于C語言并不是面向?qū)ο蟮恼Z言,C語言沒有直接提供封裝、繼承、組合、多態(tài)等面向?qū)ο蟮墓δ埽獵語言有struct和函數(shù)指針。我們可以用struct中的數(shù)據(jù)和函數(shù)指針,以此來模擬對象和類的行為。

所以在正式開始設(shè)計模式前,先看看如何用C語言實現(xiàn)面向?qū)ο缶幊獭?/span>

本章針對面向?qū)ο蟮姆庋b、繼承、組合、多態(tài)給出C語言的實現(xiàn)方法。

封裝

封裝是指對象僅暴露必要的對外接口(這里指public方法)來和其它對象進行交互,其它的屬性和行為都無需暴露,這使得對象的內(nèi)部實現(xiàn)可以自由修改。

這也要求對象包含它能進行操作所需要的所有信息,不必依賴其它對象來完成自己的操作。

以下以電力公司的例子演示封裝。

電力公司生產(chǎn)并提供電力。為了匯聚各種發(fā)電廠的電力并讓用戶獲得電力,電力公司提供了兩個統(tǒng)一接口:

1、電力公司匯聚各種發(fā)電廠的電力,無論是火力發(fā)電廠、水力發(fā)電廠、原子能發(fā)電廠等都使用一個接口。如果什么時候一家火力發(fā)電廠改造成了風力發(fā)電廠,發(fā)電廠的實現(xiàn)完全不一樣了,但接口不變,所以電力公司感覺不到發(fā)電廠變了,不需要為了發(fā)電廠實現(xiàn)升級而改造電力公司的系統(tǒng)。

2、電力公司向用戶提供電力,無論用戶用電的設(shè)備是烤面包機還是洗衣機,電力公司和用戶之間都使用一個接口(電源插座)。用戶的用電設(shè)備可以千變?nèi)f化,但接口(電源插座)不變。所以電力公司不用關(guān)系用戶的什么設(shè)備在用電。

代碼:

#include  struct PowerCompany { int powerReserve; void (*PowerPlant)(struct PowerCompany *this, int power); void (*PowerUser)(struct PowerCompany *this, int power);
}; void PowerPlant(struct PowerCompany *this, int power) { this->powerReserve += power; printf("默認發(fā)電廠,發(fā)電%d瓦\n", power); return;  
} void PowerUser(struct PowerCompany *this, int power) { if (this->powerReserve >= power) { printf("用電%d瓦\n", power); this->powerReserve -= power;
    } else { printf("電力不足,用電失敗\n");
    } return;
} /* struct PowerCompany 的構(gòu)造函數(shù) */ void PowerCompany(struct PowerCompany *this) { this->powerReserve = 0; this->PowerPlant = PowerPlant; this->PowerUser = PowerUser; return;
} /* struct PowerCompany 的析構(gòu)函數(shù) */ void _PowerCompany(struct PowerCompany *this)
{

} int main(void) { struct PowerCompany myPowerCompany; PowerCompany(&myPowerCompany); /* 發(fā)電 */ myPowerCompany.PowerPlant(&myPowerCompany, 1000); /* 用電 */ myPowerCompany.PowerUser(&myPowerCompany, 800);
    myPowerCompany.PowerUser(&myPowerCompany, 800);
    
    _PowerCompany(&myPowerCompany); return 0;
}

從電力公司的例子中可以看出,良好的封裝可以有效減少耦合性,封裝內(nèi)部實現(xiàn)可以自由修改,對系統(tǒng)的其它部分沒有影響。

繼承

面向?qū)ο缶幊套顝姶蟮墓δ苤痪褪谴a重用,而繼承就是實現(xiàn)代碼重用的主要手段之一。繼承允許一個類繼承另一個類的屬性和方法。

我們可以通過識別事物之間的共性,通過抽象公共屬性和行為來構(gòu)造父類,而通過繼承父類來構(gòu)造各子類。父類,即公共屬性和行為,就得到了復(fù)用。

以下哺乳動物的例子演示繼承。

貓和狗都是哺乳動物,它們具有公共的屬性和行為。比如,貓和狗都有眼睛,且它們都會叫。

我們把眼睛的顏色、會叫抽象出來,作為哺乳動物父類的屬性,讓貓類、狗類都繼承哺乳動物父類,可實現(xiàn)對”眼睛的顏色“、”會叫“實現(xiàn)的復(fù)用。

UML:

代碼:

#include  struct Mammal { int eyeColor; void (*ShowEyeColor)(struct Mammal *this); int callNum; void (*Call)(struct Mammal *this);
}; void ShowEyeColor(struct Mammal *this) { if (this->eyeColor == 1) { printf("眼睛是綠色\n");
    } else { printf("眼睛是藍色\n");
    } return;
} void Call(struct Mammal *this) { printf("叫%d聲\n", this->callNum); return;
} // struct Mammal 的構(gòu)造函數(shù) void Mammal(struct Mammal *this, int eyeColor, int callNum) { this->eyeColor = eyeColor; this->ShowEyeColor = ShowEyeColor; this->callNum = callNum; this->Call = Call; return;  
} struct Dog { struct Mammal mammal; }; // struct Dog 的構(gòu)造函數(shù) void Dog(struct Dog *this, int eyeColor, int callNum) {
    Mammal(this, eyeColor, callNum); // 狗類的其它屬性,略 return;
} // struct Dog 的析構(gòu)函數(shù) void _Dog(struct Dog *this)
{

} struct Cat { struct Mammal mammal; // 貓類的其它屬性,略 }; // struct Cat 的構(gòu)造函數(shù) void Cat(struct Cat *this, int eyeColor, int callNum) {
    Mammal(this, eyeColor, callNum); return;
} // struct Cat 的析構(gòu)函數(shù) void _Cat(struct Cat *this)
{

} int main(void) { struct Dog myDog; Dog(&myDog, 1, 3);
    myDog.mammal.ShowEyeColor(&myDog);
    myDog.mammal.Call(&myDog);
    _Dog(&myDog); struct Cat myCat; Cat(&myCat, 2, 5);
    myCat.mammal.ShowEyeColor(&myCat);
    myCat.mammal.Call(&myCat);
    _Cat(&myCat); return 0;
}

多態(tài)

多態(tài)與繼承是緊耦合的關(guān)系,但它通常作為面向?qū)ο蠹夹g(shù)中最強大的優(yōu)點之一。

子類從繼承父類的接口,每個子類是單獨的實體,每個子類需要對同一消息有單獨的應(yīng)答。

每個子類對同一消息的應(yīng)答采用繼承的相同接口,但每個子類可以有不同的實現(xiàn),這就是多態(tài)。

在貓和狗的例子中,貓類、狗類都繼承了哺乳動物父類的“叫”的方法,但貓類、狗類的叫聲并不一樣,所以貓類、狗類可以采用不同的“叫”的實現(xiàn)。

以下代碼演示了多態(tài)。

代碼:

#include  struct Mammal { int eyeColor; void (*ShowEyeColor)(struct Mammal *this); int callNum; void (*Call)(struct Mammal *this);
}; void ShowEyeColor(struct Mammal *this) { if (this->eyeColor == 1) { printf("眼睛是綠色\n");
    } else { printf("眼睛是藍色\n");
    } return;
} void Call(struct Mammal *this) { printf("叫%d聲\n", this->callNum); return;
} /* struct Mammal 的構(gòu)造函數(shù) */ void Mammal(struct Mammal *this, int eyeColor, int callNum) { this->eyeColor = eyeColor; this->ShowEyeColor = ShowEyeColor; this->callNum = callNum; this->Call = Call; return;  
} struct Dog { struct Mammal mammal; }; void Bark(struct Dog *this) { int i; for (i = 0; i < this->mammal.callNum; i++) { printf("汪 ");
    } printf("\n"); return;
} /* struct Dog 的構(gòu)造函數(shù) */ void Dog(struct Dog *this, int eyeColor, int callNum) {
    Mammal(this, eyeColor, callNum); this->mammal.Call = Bark; return;
} // struct Dog 的析構(gòu)函數(shù) void _Dog(struct Dog *this)
{

} struct Cat { struct Mammal mammal; }; void Meow(struct Cat *this) { int i; for (i = 0; i < this->mammal.callNum; i++) { printf("喵 ");
    } printf("\n"); return;
} /* struct Cat 的構(gòu)造函數(shù) */ void Cat(struct Cat *this, int eyeColor, int callNum) {
    Mammal(this, eyeColor, callNum); this->mammal.Call = Meow; return;
} // struct Cat 的析構(gòu)函數(shù) void _Cat(struct Cat *this)
{

} int main(void) { struct Dog myDog; Dog(&myDog, 1, 3); struct Cat myCat; Cat(&myCat, 2, 5); struct Mammal *myMammal; myMammal = &myDog;
    myMammal->Call(myMammal);
    myMammal = &myCat;
    myMammal->Call(myMammal);

    _Dog(&myDog);
    _Cat(&myCat); return 0;
}

組合

組合與繼承都是面向?qū)ο笾写a復(fù)用的方式,也只有通過組合和繼承兩種方式能夠?qū)崿F(xiàn)使用其他類構(gòu)建新類。

在前面講的繼承關(guān)系中,我們把通用屬性和行為抽象出來作為父類。

例如:貓、狗都是哺乳動物,它們具有哺乳動物通用的屬性和行為。貓、狗與哺乳動物的關(guān)系是“is-a”,即貓、狗(is-a)哺乳動物。而組合關(guān)系體現(xiàn)的是“has-a”。以房子和窗戶的關(guān)系舉例。

我們可以單獨構(gòu)建窗戶類,然后把窗戶類應(yīng)用到各種房子類上。此時房子(has-a)窗戶,但絕不是窗戶(is-a)房子。

以下UML和代碼演示了組合。

UML:

代碼

#include  struct Window { int length; int width; void (*ShowWindow)(struct Window *this);
}; void ShowWindow(struct Window *this) { printf("這是長%d厘米、寬%d厘米的窗戶\n", this->length, this->width); return;
} void Window(struct Window *this, int length, int width) { this->length = length; this->width = width; this->ShowWindow = ShowWindow; return;
} void _Window(struct Window *this)
{

} struct House { struct Window *window; int livingRoomNum; int bedRoomNum; int bathRoomNum; void (*ShowHouse)(struct House *this);
}; void ShowHouse(struct House *this) { printf("這是%d室%d廳%d衛(wèi)的房子\n", this->bedRoomNum, this->livingRoomNum, this->bathRoomNum); return;
} void House(struct House *this, int livingRoomNum, int bedRoomNum, int bathRoomNum) { this->livingRoomNum = livingRoomNum; this->bedRoomNum = bedRoomNum; this->bathRoomNum = bathRoomNum; this->ShowHouse = ShowHouse; return;
} void _House(struct House *this)
{

} void main() { struct House myHouse; House(&myHouse, 2, 3, 2); /* 組合是一種低耦合,如果不初始化,子類只是存放了一個空指針來占位關(guān)聯(lián)。
       此處是與繼承關(guān)系的區(qū)別。繼承是一種強耦合,在繼承關(guān)系中,無論如何子類擁有父類全部的信息。*/ struct Window myWindow1; myHouse.window = &myWindow1;
    Window(myHouse.window, 100, 50); /* 通過獲得其它對象的引用而在“運行時”動態(tài)定義 */ myHouse.ShowHouse(&myHouse);
    myHouse.window->ShowWindow(myHouse.window);

    _Window();
    _House(); return;
}

組合和繼承的區(qū)別有以下幾點:

組合關(guān)系體現(xiàn)的是“has-a”。繼承關(guān)系體現(xiàn)的是“is-a”。


免責聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動電源

在工業(yè)自動化蓬勃發(fā)展的當下,工業(yè)電機作為核心動力設(shè)備,其驅(qū)動電源的性能直接關(guān)系到整個系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動勢抑制與過流保護是驅(qū)動電源設(shè)計中至關(guān)重要的兩個環(huán)節(jié),集成化方案的設(shè)計成為提升電機驅(qū)動性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機 驅(qū)動電源

LED 驅(qū)動電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個照明設(shè)備的使用壽命。然而,在實際應(yīng)用中,LED 驅(qū)動電源易損壞的問題卻十分常見,不僅增加了維護成本,還影響了用戶體驗。要解決這一問題,需從設(shè)計、生...

關(guān)鍵字: 驅(qū)動電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動電源的公式,電感內(nèi)電流波動大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計 驅(qū)動電源

電動汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動汽車的核心技術(shù)之一是電機驅(qū)動控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機驅(qū)動系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動汽車的動力性能和...

關(guān)鍵字: 電動汽車 新能源 驅(qū)動電源

在現(xiàn)代城市建設(shè)中,街道及停車場照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進步,高亮度白光發(fā)光二極管(LED)因其獨特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動電源 LED

LED通用照明設(shè)計工程師會遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動電源的電磁干擾(EMI)問題成為了一個不可忽視的挑戰(zhàn)。電磁干擾不僅會影響LED燈具的正常工作,還可能對周圍電子設(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動電源

開關(guān)電源具有效率高的特性,而且開關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機重量也有所下降,所以,現(xiàn)在的LED驅(qū)動電源

關(guān)鍵字: LED 驅(qū)動電源 開關(guān)電源

LED驅(qū)動電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動電源
關(guān)閉