色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

應用面向對象編程SoC原則的典型示例

AGk5_ZLG_zhiyua ? 來源:互聯(lián)網 ? 作者:佚名 ? 2018-02-05 09:36 ? 次閱讀

周立功教授新書《面向AMetal框架與接口編程(上)》,對AMetal框架進行了詳細介紹,通過閱讀這本書,你可以學到高度復用的軟件設計原則和面向接口編程的開發(fā)思想,聚焦自己的“核心域”,改變自己的編程思維,實現(xiàn)企業(yè)和個人的共同進步。經周立功教授授權,即日起,致遠電子公眾號將對該書內容進行連載,愿共勉之。

第九章為BLE&zigbee 無線模塊,本文內容為9.3 MVC 框架。

>>> 9.3.1 MVC 模式

模型-視圖-控制器(Model-View-Controller,MVC)模式是應用面向對象編程 SoC 原則的典型示例,模式的名稱來自用于切分軟件應用的三個主要部分,即模型部分、視圖部分和控制器部分。它是 Smalltalk 中的用戶界面框架,其目的是將模型從用戶界面解耦。因為 Model相對來說比較穩(wěn)定,而 View 和 Controller 相對來說容易變化,所以通過分層可以隔離變化。

而且視圖與模型的分離帶來的好處允許美工專心設計 UI 部分,程序員專心開發(fā)軟件,互相不會干擾。MVC 包括 3 類組件:

  • Model:模型代表應用信息,負責“內部實現(xiàn)”的具體功能,包含和管理(業(yè)務)邏輯、數(shù)據、狀態(tài)以及應用的規(guī)則,不依賴 UI;

  • View:通常在一個人機接口上呈現(xiàn) Model 信息的抽象視圖,即視圖是模型的外在表現(xiàn)——用戶界面的一部分,視圖只是展示數(shù)據,但不處理數(shù)據。視圖并非一定是圖形化的,文本輸出也是視圖;

  • Controller:將用戶輸入分配到模型與視圖中去,控制器也是用戶界面的一部分,定義用戶界面對用戶輸入的響應方式。

如圖 9.10 所示為 MVC 框架的示意圖,視圖和控制器合起來組成用戶界面,用戶界面包括輸入和輸出兩部分:視圖相當于輸出部分——顯示結果給用戶,控制器相當于輸入部分——響應用戶的操作。這 3 類組件通過交互進行協(xié)作,View創(chuàng)建 Controller 后,Controller 根據用戶交互調用Model 的相應服務。而 Model 會將自身狀態(tài)的改變通知View,View則會讀取Model的信息更新自身。比如,當用戶通過單擊(鍵入或觸摸等)某個按鈕觸發(fā)一個視圖時,視圖將用戶操作告知控制器。控制器處理用戶輸入,并與模型交互。模型執(zhí)行所有必要的校驗和狀態(tài)改變,并通知控制器應該做什么。控制器按照模型給出的指令,指導視圖更新顯示內容輸出。

圖 9.10 MVC 框架示意圖

通常 MVC 被認為是一種框架模式,而不是一種設計模式,因為框架模式與設計模式之間的區(qū)別在于,前者比后者的范疇更廣泛。其主要特征在于它能夠為多個不同的視圖提供數(shù)據,即同一個模型可以支持多個視圖,模型的代碼只需要寫一次就可以被多個視圖重用。假設在兩個視圖中使用同一個模型的數(shù)據,無論何時更改了模型,都需要更新兩個視圖,可以使用觀察者模式解決。

>>> 9.3.2 觀察者模式

觀察者模式定義了一對多的對象之間的依賴關系,當一個對象的狀態(tài)發(fā)生變化時,所有依賴于它的對象都會得到通知并自動更新,因此觀察者模式是一種行為模式,其適用于根據觀察對象狀態(tài)進行相應處理的場景。

在溫度檢測儀中,當溫度傳感器得到的值發(fā)生變化時,希望視圖的內容同步改變。雖然可以在溫度檢測代碼中附加更新顯示的功能,但在本質上更新顯示與溫度檢測是完全不同的兩種處理方法,因此相互之間形成了高度依賴性的關系。

觀察者模式就是一種避免高度依賴性的方法,構成觀察者模式的有兩個對象:發(fā)生變化的對象稱為 觀察對象(Subject),而被通知的對象稱為 觀察者(Observer)。如果觀察對象的狀態(tài)發(fā)生變化,則所有的觀察者都會收到消息,同步更新自己的狀態(tài),因此這種交互方式又被稱為“依賴”或“發(fā)布—訂閱”。雖然觀察對象是消息的發(fā)布者,但它發(fā)布消息時并不需要知道誰是它的觀察者,因此觀察者的數(shù)量是不限的,即觀察對象維護了觀察者對象的結合。現(xiàn)在的問題是,如果觀察者與觀察對象互相引用,它們變得互相依賴,這可能會對一個系統(tǒng)的分層和重用性產生負面影響。基于此,觀察者模式通過定義一個接口通知觀察對象發(fā)生了變化,從而將觀察者與觀察對象解耦,只依賴于觀察者和觀察對象的抽象類,從而保證了訂閱系統(tǒng)的靈活性和可擴展性。

圖 9.11 觀察者模式的實現(xiàn)結構

在如圖 9.11 所示的觀察者模式的結構圖中,觀察者類(Observer)、觀察對象類(Subject)、具體的觀察者類(ConcreteObserver)和具體的觀察對象類(ConcreteSubject)共同完成觀察者模式的各項職責,使用“添加、通知和刪除”的方法實現(xiàn)觀察者模式。

  • Observer(觀察者):Observer 角色負責接收來自 Subject 角色狀態(tài)變化的通知,即Subject 調用每個 Observer 的 update 方法,發(fā)消息通知所有的 Observer,從而將 Subject 和Observer 解耦。因此,當對象間有數(shù)據依賴時,最好用觀察者模式對它們解耦。

    由于 Observer 角色是抽象的,雖然它聲明了 update 方法,但不提供任何實現(xiàn),該方法在子類中實現(xiàn)。

  • Subject(觀察對象):Subject 角色表示觀察對象,定義觀察對象必須實現(xiàn)的職責:管理(添加或刪除)觀察者并通知觀察者。從 Subject 指向 Observer 的箭頭線表明 Subject包含了 Observer 類型的實例,箭頭前面的實心圓圈表示多于一個實例。

    當觀察對象的狀態(tài)變化時,由于它不知道該將消息發(fā)送給誰,因此 Subject 角色定義了一個可以存儲 N 個觀察者對象“列表”,以及添加(attach)、刪除(detach)和通知(notify)觀察者的抽象方法。

    當觀察對象決定通知它的所有觀察者對象時,notify 遍歷觀察者對象“列表”,調用每個 Observer 的 update 方法,發(fā)消息通知所有的 Observer,告訴它們“我的狀態(tài)改變了,請更新顯示內容”。如果在 Subject 角色中注冊了多個 Observer 角色,誰先注冊就先調用誰的update 方法,不能改變調用順序。

  • ConcreteObserver(具體的觀察者):ConcreteObserver 角色表示具體的觀察者,當它的方法被調用后,就會去獲取具體的觀察對象的最新狀態(tài)。從 ConcreteObserver 指向ConcreteSubject 的箭頭線表明 ConcreteObserver 包含了 ConcreteSubject 類型的實例,由于沒有實心圓圈,則表示有且僅有一個實例。

  • ConcreteSubject (具體的觀察對象):ConcreteSubject 角色表示具體的觀察對象,其職責非常明確——誰能觀察,誰不能觀察。它不僅提供函數(shù)的實現(xiàn),而且提供獲取和管理它發(fā)布數(shù)據的方法。當自身的狀態(tài)發(fā)生改變時,它會通知所有已經注冊的 Observer 角色。除了要支持 Subject 角色外,根據業(yè)務的不同,可能還需要提供諸如 getState()、setState()這樣的函數(shù),用于具體的觀察者獲取或設置相關的狀態(tài)。

觀察者模式中的 Subject 和 Observer 接口是為了處理 Subject 的變化而設計的,因此當對象之間有數(shù)據依賴時,最好用觀察者模式對它們進行解耦。觀察者模式的適用范圍如下:

  • 當一個抽象模型有兩個方面時,如果其中一個方面依賴于另一個方面,則只要將這兩者封裝在獨立的對象中,即可使它們各自獨立地改變和復用。

  • 當改變一個對象需要同時改變其它對象時,卻不知道具體有多少個對象有待改變。

  • 當一個對象必須通知其它對象時,而又無法預知其它對象是誰,而你不希望這些對象是緊耦合的。

注意事項:

  • 在觀察者模式中,觀察對象通知了觀察者,而這個觀察者同時也是一個觀察對象,它會通知其它的觀察者。因而常常會產生過于復雜的設計,并且使調試變得更加困難。當遇到這種情況時,Mediator(仲裁)模式可能會幫助我們改進這類代碼。

    根據經驗建議,最多允許出現(xiàn)一個對象既是觀察者也是觀察對象,即消息最多轉發(fā)一次(兩次),否則邏輯關系就會比較復雜且難以維護。

  • 如果觀察者比較多,且處理時間比較長,雖然可以使用異步處理方式,但要考慮線程安全和隊列問題。

  • 當觀察者與觀察對象的關系是一對多時,一是使用多線程技術(異步),不管誰啟動線程,都可以明顯地提高系統(tǒng)性能。二是使用緩存技術(同步),但需要足夠多的資源。

  • 觀察對象可以自己做主決定是否通知觀察者,以達到減輕負擔的目的。

MVC 框架是一個典型的觀察者模式示例,Model 提供的數(shù)據是 View 的觀察對象,發(fā)布者是 Model,訂閱者是 View。Model 是指操作“不依賴于顯示形式的內部模型”,View 是管理 Model“如何顯示”的,通常一個 Model 對應多個 View。

下面將以 AM824ZB 開發(fā)板為載體展示 MVC 框架,當視圖觀察到模型生成的布爾類型value 值時,既可以通過 LED0 顯示,也可以通過 zigbee 發(fā)送出去,使得可以無線遠程監(jiān)控value 的值。其用例描述如下:

在初始狀態(tài)時,value 為 AM_FALSE, LED 熄滅,zigbee 發(fā)送“0”。當有鍵按下時,則 value 值為 AM_TRUE,LED 點亮,zigbee 發(fā)送“1”;當鍵再次按下時,則 value 值為AM_FALSE,LED0 熄滅,zigbee 發(fā)送“1”......如此周而復始。

其中,value 值對應于 Observer 模式中的模型, LED 和 zigbee 對應于 Observer 模式中的視圖,Observer 模式描述了基本數(shù)據和它可能為數(shù)眾多的用戶界面元素之間的關系。

  • 每份數(shù)據都被封裝在一個 Subject 對象中;

  • 與 Subject 對應的每個用戶界面元素被封裝在一個 Observer 對象中;

  • 一個 Subject 同時可以有多個 Observer;

  • 當一個 Subject 改變時,會通知它所有的 Observer;

  • Observer 也會從對應的 Subject 處獲取相應的信息,并及時更新顯示內容。

最終的信息存儲在 Subject 中,當 Subject 中的信息發(fā)生變化時,Observer 會及時更新相應的顯示內容。當用戶保存數(shù)據時,其保存的是 Subject 中的信息,而 Observer 中的信息不需要保存,因為它們顯示的信息來自對應的 Subject。

Observer 模式規(guī)定了單獨的 Subject 類層次和 Observer 類層次,其中的抽象基類定義了通知的協(xié)議,以及用于添加(attach)和刪除(detach)視圖的 Observer 的接口。ConcreteSubject子類實現(xiàn)特定的接口,為了讓具體的 Observer 知道什么東西發(fā)生了變化,它還需要增加相應的接口,同時 ConcreteObserver 子類通過它們的 update 操作指定如何對自己進行更新,從而以獨一無二的方式顯示它們的 Subject。

>>> 9.3.3 領域模型

1. 類模型

創(chuàng)建類模型的第一步就是從問題域尋找相關的對象類,類常常與名詞對應,不要精挑細選,要記下所有可能的每個類。因為我們的目的是捕獲概念,一方面并不是所有的名詞都是概念,另一方面概念也會在語句的其它部分中得到體現(xiàn)。比如,暫定類為 value(bool 值)、key(按鍵)、LED(發(fā)光二極管)和 zigbee。然后通過共性和差異化分析,將它們歸類到更廣泛的范疇內。

雖然 LED 和 zigbee 屬于不同類型的對象,且它們的顯示函數(shù)也不一樣,但它們共同的概念是“視圖”和“顯示函數(shù)”。LED 具有“編號(led_id)”屬性,比如,LED0 的編號“0”用 led_id 表示,而 zigbee 具有“實例句柄(zm516x_handle)”屬性,通過實例句柄即可進行數(shù)據的收發(fā)。因此將共同的概念用抽象類 observer_t 表示,其中的屬性通過具體類 view_led_t和 view_zigbee_t 實現(xiàn)。

雖然 value 是一個 am_bool_t 值,可以將它歸類到業(yè)務邏輯,但同樣要對它建模,創(chuàng)建相應的基類 model_t 和具體類 model_bool_t,而 value 是model_bool_t 的屬性。

下一步是尋找類間的關聯(lián),兩個或多個類之間的結構化關系就是關聯(lián),從一個類到另一個類的引用也是關聯(lián),因此 model_t 與 observer_t 是一對多的關系。接著使用繼承共享公共結構組織類,其相應的類模型詳見圖 9.12。

圖 9.12 類模型

2. 交互模型

顯然有了類,即可創(chuàng)建模型對象model_bool 與視圖對象 view_led0 和view_zigbee。由于視圖需要知道如何調用顯示函數(shù),因此將通過在類中定義方法表示這些職責。當模型對象的狀態(tài)變化時,需要調用視圖對應的顯示函數(shù) view_update 才能更新顯示內容。雖然不同視圖(LED 視圖、zigbee視圖)的顯示函數(shù)的實現(xiàn)不一樣(LED 亮滅、zigbee 發(fā)送“0”或“1”),但其共性是“顯示函數(shù)”,因此可以共用 pfn_update_view 函數(shù)指針調用顯示函數(shù)。

如圖 9.13 所示的類-職責-協(xié)作序列圖展示了 model_bool、view_led0 和 view_zigbee 對象之間的消息流和由消息引起的方法調用。

圖 9.13 類-職責-協(xié)作序列圖

當有鍵按下時,即可調用 model_bool_set()修改模型對象的 value 值。當模型對象 value值改變后,調用 model_notify()遍歷視圖對象鏈表通知所有的視圖,即調用視圖顯示函數(shù)pfn_update_view()。視圖對象在 pfn_update_view()函數(shù)的實現(xiàn)中,調用 model_bool_get()從模型對象中獲取 value 值,以便更新顯示內容。

>>> 9.3.4 子系統(tǒng)體系結構

集成通信圖是所有開發(fā)用于支持用例的通信圖的合成,其形象地描述了對象之間的相互連接以及所傳遞的消息。通常不同用例之間存在執(zhí)行的優(yōu)先順序,通信圖合成的順序應該與用例執(zhí)行的順序一致,MVC 框架的子系統(tǒng)接口圖詳見圖 9.14。

圖 9.14 子系統(tǒng)接口圖

  • 按鍵

當 key1 鍵按下時,則布爾模型的值發(fā)生改變。首先通過 model_bool_get()得到當前的布爾值,接著將該布爾值取反,然后調用 model_bool_set()將取反后的布爾值重新設置到布爾模型中。

  • 布爾模型

布爾模型負責維護一個布爾值,外界可以通過 model_bool_set()設置布爾值,也可以通過 model_bool_get()獲取布爾值。當布爾值發(fā)生改變時,布爾模型將依次調用各個視圖的顯示更新函數(shù) pfn_update_view()通知各個視圖更新顯示,各視圖根據自身功能決定顯示方式。

  • 視圖

圖中包含了兩個視圖:view_led0 和 view_zigbee。

當 LED0 視圖(view_led0)接收到布爾模型發(fā)出的更新顯示通知時,首先通過模型接口 model_bool_get()獲取當前模型的布爾值。若值為 AM_TRUE,則調用 am_led_on()點亮LED0;若值為 AM_FALSE,則調用 am_led_off()熄滅 LED0。

當 zigbee 視圖(view_zigbee)接收到布爾模型發(fā)出的更新顯示通知時,首先通過模型接口 model_bool_get()獲取當前模型的布爾值,然后通過 am_zm516x_send ()函數(shù)將布爾值通過 zigbee 發(fā)送出去。

>>> 9.3.5 軟件體系結構

1. 設計模型類圖

由于觸發(fā)事件的模型對象無法預測訂閱該事件的所有視圖對象,因此要求將視圖添加到模型的列表中保存起來。雖然可以將與模型關聯(lián)的視圖對象存放在數(shù)組中,卻不利于在運行時動態(tài)地添加和刪除視圖,因此選擇單向鏈表。

圖 9.15 單向鏈表示意圖

單向鏈表是由一個 slist_head_t 類型的頭結點和若干個 slist_node_t 類型的普通結點“鏈”起來的,其示意圖詳見圖 9.15,鏈表的數(shù)據結構定義如下:

由于模型需要管理(添加、刪除和遍歷)存儲視圖的鏈表,因此模型需要“持有”整個視圖鏈表的頭結點。基于此,需要將鏈表的 slist_head_t 類型(slist.h)頭結點 head 包含在model_t 抽象模型類中作為數(shù)據成員:

其中,head 為鏈表的頭結點指針,指向存儲視圖的鏈表,其相應的數(shù)據結構示意圖詳見圖 9.16。由于視圖對象是存儲在單向鏈表中的一個結點,因此需要將鏈表的 slist_node_t 類型(slist.h)普通結點 node 包含在 observer_t 抽象視圖類中作為數(shù)據成員:

圖 9.16 模型數(shù)據結構圖

當需要增加視圖、刪除視圖或遍歷視圖時,將會用到與鏈表對應的 4 個接口函數(shù)。下面將逐一介紹,并在定義了 model_t 類型的模型對象 model 和 observer_t 類型的視圖對象observer 的前提下,展示了接口的調用形式。

  • 鏈表初始化

鏈表初始化的函數(shù)原型如下:

其調用形式如下:

在初始狀態(tài)時,模型與視圖沒有任何關系,而添加和刪除視圖是調用 model_attach()和model_detach()實現(xiàn)的,這是分別調用插入鏈表結點函數(shù) slist_add_head()和刪除鏈表結點函數(shù) slist_del()實現(xiàn)的。

  • 添加視圖

添加視圖的 slist_add_head()函數(shù)原型如下:

其調用形式如下:

  • 刪除視圖

刪除視圖的 slist_del()函數(shù)原型如下:

其調用形式如下:

圖 9.17 模型內部狀態(tài)圖

如圖 9.17 所示在模型內部的鏈表中添加和刪除視圖的狀態(tài)圖,圖中的 attach/detach 省略了 model_固定前綴。當調用 model_attach()時,則模型關聯(lián)了一個視圖,即從初始狀態(tài)轉移到關聯(lián)一個視圖狀態(tài)。當再次調用 model_attach()時,則模型對象關聯(lián)了兩個視圖,即從關聯(lián)一個視圖狀態(tài)轉移到兩個視圖狀態(tài),以此類推。

在觀察對象的聲明周期中,如果不需要刪除視圖的功能,則不要實現(xiàn) model_detach()。如果不需要在運行時動態(tài)地添加和刪除視圖,即可在初始化時將視圖存儲在數(shù)組中,那么不再需要 model_attach()和 model_detach()函數(shù)。

  • 遍歷視圖

當模型的狀態(tài)發(fā)生變化時,則需要調用 model_notify()遍歷保存在模型中的視圖鏈表,并調用每個視圖的 pfn_update_view(),才能通知所有的視圖更新顯示內容。而 model_notify()又是調用遍歷鏈表函數(shù) slist_foreach()實現(xiàn)的,遍歷視圖的 slist_foreach()函數(shù)原型如下:

其調用形式如下:

除了在序列圖中顯示了對象協(xié)作的動態(tài)視圖外,還需要設計模型類圖表示類定義的靜態(tài)視圖描述類的屬性和方法。由于鏈表屬于基礎設施領域的概念,不是業(yè)務邏輯領域的概念,說明復用級別是基于基礎設施域的,沒有基于核心域,因此存儲視圖的是數(shù)組、鏈表還是其它的容器,都不影響核心域的概念。這就是鏈表不會出現(xiàn)在分析工作流中,只有設計工作流中才考慮的原因。基于此,不僅需要將鏈表的 slist_head_t 類型(slist.h)頭結點 head 包含在model_t 抽象模型類中作為數(shù)據成員,而且需要將鏈表的 slist_node_t 類型(slist.h)普通結點node包含在observer_t抽象視圖類中作為數(shù)據成員。

圖 9.18 設計模型類圖

如圖 9.18所示為 MVC框架的設計模型類圖,圖中的“0..*”說明模型與視圖呈現(xiàn)一對多的關系。顯然基類的方法子類也有,由于 model_attach()、model_detach()和model_notify()是在model_t類的接口中實現(xiàn)的,而在 model_bool_t 子類中沒有實現(xiàn),因此在繪制 UML 圖時則不需要重復表示,但子類還是繼承了父類的方法。而 observer_t 基類的 pfn_update_view()抽象方法是在子類中實現(xiàn)的,因此在繪制 UML 圖時必須顯式地表示。

2. 抽象視圖/ 模型

(1)抽象視圖類

當模型對象的狀態(tài)變化時,所有視圖共用函數(shù)指針 pfn_update_view,調用各自對應的顯示函數(shù) view_update 更新顯示內容。update_view_t 類型定義如下:

在面向對象 C++編程中時,方法是通過一個隱式的 p_this 指針,使其指向函數(shù)要操作的對象,訪問自身的數(shù)據成員。而在面向對象 C 編程時,則需要顯式地聲明 p_this 指針。使其指向函數(shù)將要操作的視圖對象,訪問視圖對象的數(shù)據成員。

p_model 指向視圖觀察的模型,其目的是獲取模型的數(shù)據,使顯示數(shù)據與模型數(shù)據保持一致。由于 pfn_update_view()方法使用了模型類定義的指針變量 p_model,而在該函數(shù)的實現(xiàn)中調用了模型類的方法 model_bool_get(),即一個類使用了另一個類的操作,因此可以說視圖依賴于模型。

依賴是兩個元素之間的一種關系,其中一個元素變化,將會導致另一個元素變化。雖然依賴的同義詞就是耦合和共生,但依賴是不可避免的,重要的是如何務實地應付變化,這就是良性依賴原則。通常在 UML 中將依賴畫成一條有向的虛線,指向被依賴的類。

由此可見,良性依賴可以幫助我們抵御 SOLID 原則與設計模式的誘惑,以免陷入過度設計的陷阱,帶來不必要的復雜性。

由于鏈表的每個結點存儲都是視圖,因此遍歷視圖鏈表需要從頭結點 node 開始。這是一種常見的 is-a 層次結構,其共同的概念用抽象類表示,差異化分析所發(fā)現(xiàn)的變化將通過從抽象類派生而來的具體類實現(xiàn)。observer_t 抽象類的定義如下:

其中,node 為鏈表結點成員,pfn_update_view 指向與視圖對應的顯示函數(shù),比如,view_update,抽象類 observer_t 的類圖詳見圖 9.19。

圖 9.19 抽象視圖類

顯然,有了 observer_t 類,就可以定義相應的實例 view,當將對象 view 的地址傳給形參 p_this 后:

即可按 this 的指向引用其它成員。

雖然 pfn_update_view 看起來是一個“數(shù)據成員”,但從概念視角來看,其定義的是一個在具體視圖類中實現(xiàn)的抽象方法,其目的是將模型和視圖“解耦”。

在面向對象編程時,每個對象(類)都有一個用于對象初始化的“構造函數(shù)”,初始化成員變量等,而 C 語言則需要顯式地調用 view_init()初始化函數(shù)。其函數(shù)原型如下:

其中,p_this 指向視圖對象,pfn_update_view 指向與視圖對應的顯示函數(shù),其調用形式詳見程序清單 9.54。

程序清單 9.54 視圖初始化函數(shù)范例程序

在 main()中調用對象 view 的初始化函數(shù) view_init(),用 OOP 術語來說,這是給對象 view發(fā)送一條消息,通知它進行自我初始化。view_init()的實現(xiàn)詳見程序清單 9.55。

程序清單 9.55 view_init()初始化函數(shù)

在面向對象 C++編程時,雖然每個類都有“構造函數(shù)”,但有時候可能為空,因此不會將構造函數(shù)作為方法展示在類圖中。而面向對象 C 編程——雖然 view_init()看起來像抽象視圖類提供的接口,但其功能類似于“構造函數(shù)”,因此沒有呈現(xiàn)在相應的類圖中。

(2)抽象模型類

由于抽象模型僅需管理與之關聯(lián)的視圖,其本質上是管理了一個視圖鏈表,因此僅包含一個鏈表頭結。此外,還需提供增加、刪除、遍歷視圖的方法,model_t抽象類的定義如下:

其中,head 為鏈表的頭結點,其類圖詳見圖 9.20。顯然有了 model_t 類,即可定義相應的實例,當將 model 的地址傳給形參 p_model 后:

即可按 p_model 的指向引用其它成員。

圖 9.20 抽象模型類

類似地,需要初始化模型中的各個成員,其函數(shù)原型如下:

其中,p_this 指向模型對象,其調用形式如下:

model_init()模型初始化函數(shù)的實現(xiàn)詳見程序清單 9.56。

程序清單 9.56 model_init()模型初始化函數(shù)

初始化后,需要將視圖保存到鏈表中。當模型的狀態(tài)變化時,即可遍歷鏈表找到與視圖對應的顯示函數(shù),通知視圖更新顯示內容。其函數(shù)原型如下:

其中,p_this 指向模型對象,p_observer 指向視圖對象,其調用形式詳見程序清單 9.57。

程序清單 9.57 添加視圖范例程序

為了避免直接訪問數(shù)據,將通過接口函數(shù)和對象交互,model_attach()添加視圖函數(shù)的實現(xiàn)詳見程序清單 9.58。

程序清單 9.58 model_attach()添加視圖函數(shù)

如果觀察者只對某一事件感興趣,則可以擴展觀察對象的注冊接口,讓觀察者注冊為“僅對特定時間感興趣”,以提高更新的效率。

當不再使用某個視圖時,則將其從鏈表中刪除,其函數(shù)原型如下:

其中,p_this 指向模型對象,p_observer 指向視圖對象,其調用形式詳見程序清單 9.59。

程序清單 9.59 刪除視圖范例程序

model_detach()刪除視圖函數(shù)的實現(xiàn)詳見程序清單 9.60。

程序清單 9.60 model_detach()刪除視圖函數(shù)

當模型對象的狀態(tài)變化時,需要遍歷保存在模型中的視圖對象鏈表,并調用每個視圖對象的 pfn_update_view(),才能通知所有的視圖更新顯示內容。其函數(shù)原型如下:

其中,p_this 指向模型對象,其調用形式詳見程序清單 9.61。

程序清單 9.61 遍歷視圖鏈表范例程序

model_notify()通知更新顯示內容函數(shù)的實現(xiàn)詳見程序清單 9.62。

程序清單 9.62 model_notify()通知更新顯示函數(shù)

其中,slist_foreach()為遍歷視圖鏈表函數(shù),__view_process()回調函數(shù)依次處理各個鏈表結點(即視圖),“處理”就是調用視圖中的 pfn_update_view 函數(shù),其對應的函數(shù)原型為:

通常在調用 pfn_update_view 函數(shù)時,需要傳遞 2 個參數(shù),其分別為指向視圖的指針和指向模型的指針。

由于視圖的第一個成員為node,p_node為指向node的指針,其值為視圖首元素的地址,與視圖的地址相等,強制轉換即可得到指向視圖自身的指針:

此外,在 model_notify()函數(shù)調用 slist_foreach()函數(shù)時,將指向模型的指針作為回調函數(shù)的參數(shù),因此__view_process()函數(shù)中的 p_arg 為指向模型的指針。為了類型匹配,強制轉換即可得到指向模型的指針:

此前介紹的示例只是為了展示接口的使用,實際上 model_t 和 observer_t 并沒有提供具體的實現(xiàn),需要在應用中定義具體的視圖類和模型類,比如,針對 LED 顯示可以定義一個LED 視圖類,針對布爾模型可以定義一個布爾模型類。

為了便于查閱,程序清單 9.63 展示了 mvc.h 文件的內容。

程序清單 9.63 mvc.h 文件內容

  • 對稱性

其實程序中處處充滿了對稱性,比如,model_attach()方法總會伴隨著 model_detach()方法,一組方法接受同樣的參數(shù),一個對象中所有的成員都具有相同的生命周期。識別出對稱性,將它清晰地表達出來,使代碼更容易閱讀。一旦閱讀者理解了對稱性所涵蓋的某一半,自然也就很快地理解了另一半。

程序中的對稱性指的是概念上的對稱,無論在什么地方,同樣的概念都會以同樣的形式呈現(xiàn)。在準備消滅重復之前,常常需要尋找并表示出代碼中的對稱性。

3. 具體模型/ 視圖

(1)布爾模型

雖然 model_bool_t 實現(xiàn)了 model_t 接口,但抽象模型中并沒有與應用相關的業(yè)務邏輯,所以要在布爾模型中增加相應的數(shù)據,因為視圖的核心就是觀察數(shù)據并實時同步顯示。

圖 9.21 布爾模型類

雖然作為示例布爾模型僅包含一個值為 AM_TRUE 或 AM_FALSE的布爾值,但是各個視圖都可以觀察這個布爾值并實時同步顯示。其職責是管理觀察對象的狀態(tài),實現(xiàn) model_bool_get()獲取布爾值和model_bool_set()修改布爾值的方法,以及在狀態(tài)發(fā)生改變時,調用基類的方法 model_notify()通知所有關聯(lián)的視圖更新顯示內容。布爾模型的類圖詳見圖 9.21,其定義如下:

其中,am_bool_t 是 AMetal 在 am_types.h 中自定義的類型,其值為 AM_TRUE 或AM_FALSE。由于有了布爾模型,即可定義相應的實例,當將 model_bool 的地址傳給形參p_this 后:

即可按 p_this 的指向引用其它成員。

value 的初值將通過參數(shù)傳遞給初始化函數(shù),其函數(shù)原型如下:

其中,p_this 指向模型對象,init_value 為布爾模型初值。其調用形式如下:

通常應該先初始化基類化,接著再初始化自身特有數(shù)據,model_bool_init()的實現(xiàn)詳見程序清單 9.64。

程序清單 9.64 model_bool_init()模型初始化函數(shù)

由于布爾模型維護了一個 am_bool_t 類型 value 值,因此需要提供設置和獲取 value 值的接口。model_bool_set()用于設置布爾模型當前的布爾值,比如,當有鍵按下時,可以使用該接口修改布爾模型的值。在設置布爾模型的值時,可能會使布爾模型的值發(fā)生變化。當value 值改變時,視為布爾模型的狀態(tài)發(fā)生變化,此時需要調用 model_notify()通知所有的視圖。如果布爾值未發(fā)生任何改變,則無需做任何實際動作。其函數(shù)原型如下:

其中,p_this 指向模型對象,value 為設置的當前值,設置布爾模型當前值 value 的范例程序詳見程序清單 9.65。

程序清單 9.65 設置布爾模型當前值 value 的范例程序

model_bool_set()函數(shù)的實現(xiàn)詳見程序清單 9.66。

程序清單 9.66 model_bool_set()函數(shù)

類似地,model_bool_get()用于獲取布爾模型當前的布爾值,比如,當布爾模型的值發(fā)生變化時,模型會通知所有的視圖更新顯示。此時,在視圖顯示函數(shù)中,則需要調用該函數(shù)得到當前最新的布爾值,同步更新顯示。獲取 value 當前值的函數(shù)原型如下:

其中,p_this 指向模型對象,p_value 為獲取當前值的指針,獲取布爾模型當前值的范例程序詳見程序清單 9.67。

程序清單 9.67 獲取布爾模型當前值的范例程序

model_bool_get()函數(shù)的實現(xiàn)詳見程序清單 9.68。

程序清單 9.68 model_bool_get()函數(shù)

為了便于查閱,程序清單 9.69 展示了 model_bool.h 文件的內容。

程序清單 9.69 model_bool.h 文件內容

(2)具體視圖

由于具體視圖類實現(xiàn)了 observer_t 接口,因此具體視圖還必須實現(xiàn)在抽象視圖 observer_t中定義的 update 方法,即要給抽象視圖中的 pfn_update_view 函數(shù)指針賦值,使其指向實際的 update 函數(shù)。

當布爾模型的數(shù)據發(fā)生變化時,視圖顯示函數(shù)需要調用 model_bool_get()獲取最新的布爾值。當獲取布爾值后,即可根據具體視圖的實際功能同步顯示相應的數(shù)據。

對于 LED 視圖來說,則將觀察到的 bool 值通過 LED 顯示出來。即 bool 值為 AM_FALSE時 LED 熄滅,bool 值為 AM_TRUE 時 LED 點亮;對于 zigbee 視圖來說,則將觀察到的 bool值通過 zigbee 發(fā)送出去,即 bool 值為 AM_FALSE 時 zigbee 發(fā)送“0”,bool 值為 AM_TRUE時 zigbee 發(fā)送“1”。

  • LED 視圖

LED 視圖繼承自抽象視圖,同時具有一個私有數(shù)據成員 led_id,用于表示 LED 燈的 ID號,LED 視圖定義如下:

其中的 led_id 為 LED 的下標編號。LED 視圖類 view_led_t 實現(xiàn)了 observer 接口,其對應的類圖詳見圖 9.22。

圖 9.22 LED 視圖類

顯然有了 LED 視圖,即可定義相應的視圖對象,當將view_led的地址傳給形參p_view_led后:

即可按 p_view_led 的指向引用其它成員。

接著初始化視圖對象,顯然只要將 view_led、led_id 值傳遞給 view_led_init()函數(shù),即可初始化 LED 視圖對象,其函數(shù)原型(view_led.h)如下:

其中,p_view_led 指向 LED 視圖對象,led_id 為 LED 的編號。其調用形式如下:

通常需要先初始化抽象視圖(基類),接著再初始化私有數(shù)據成員 led_id 等,初始化抽象視圖的函數(shù)原型(mvc.h)如下:

在實現(xiàn) view_led_init()時,需要先實現(xiàn)與其對應的顯示函數(shù),詳見程序清單 9.70。

程序清單 9.70 LED 視圖顯示函數(shù)的實現(xiàn)

基于此,LED 視圖初始化函數(shù)的實現(xiàn)詳見程序清單 9.71。

程序清單 9.71 LED 視圖初始化函數(shù)的實現(xiàn)

視圖在得到通知后,需要知道究竟是 model_t 類中哪個狀態(tài)發(fā)生了變化,發(fā)生了何種變化。通常在通知接口 pfn_update_view 中不傳送這些信息,而是在視圖得到通知后,再反過來調用 model_bool_get()查詢狀態(tài)的函數(shù)。然后視圖再決定自己應該做什么事情,這時pfn_update_view 的參數(shù)就是 model_t 類的指針。

當布爾模型的狀態(tài)發(fā)生變化時,為了實現(xiàn)自動調用 LED 視圖對應的顯示函數(shù),那么 LED視圖需要預先將自己添加到模型對象的鏈表中保存起來。比如:

為了便于查閱,程序清單 9.72 展示了 view_led.h 文件的內容。

程序清單 9.72 view_led.h 文件內容

至此,實現(xiàn)了一個具體模型(布爾模型)和一個具體視圖(LED 視圖),具有單個視圖的模型完整示例詳見程序清單 9.73。

程序清單 9.73 單個視圖的范例程序(main.c)

  • zigbee 視圖

zigbee 視圖繼承自抽象視圖,同時具有一個私有數(shù)據成員 zm516x_handle,其為 zigbee實例句柄,通過該句柄,即可使用相應的接口函數(shù)操作 zigbee 模塊,zigbee 視圖定義如下:

zigbee 視圖類 view_zigbee_t 實現(xiàn)了 observer_t 接口,其對應的類圖詳見圖 9.23。

圖 9.23 zigbee 視圖類

有了zigbee 視圖,即可定義相應的視圖對象,當將 view_zigbee 的地址傳給 p_view_zigbee 后:

即可按 p_view_zigbee 的指向引用其它成員。

類似地,定義 zigbee 視圖的初始化函數(shù)原型如下:

其中,p_view_zigbee 指向 zigbee 視圖對象,zm516x_handle 是 zigbee 模塊的實例句柄,可通過 ZM516X 模塊的實例初始化函數(shù)獲得。其調用形式如下:

在實現(xiàn) view_zigbee_init()時,也需要先實現(xiàn)與其對應的顯示函數(shù),詳見程序清單 9.74。

程序清單 9.74 zigbee 視圖顯示函數(shù)的實現(xiàn)

其中,am_zm516x_send()函數(shù)的作用是通過 zigbee 發(fā)送字符串至目標地址的節(jié)點(目標地址在初始化時配置),其函數(shù)原型(am_zm516x.h)為:

基于此,zigbee 視圖初始化函數(shù)的實現(xiàn)詳見程序清單 9.75,其除了初始化抽象視圖類外,還完成了 zigbee 模塊的地址配置,配置本地地址為 0x2001,目標地址為 0x2002。

程序清單 9.75 zigbee 視圖初始化函數(shù)的實現(xiàn)

為了便于查閱,程序清單 9.76 展示了 view_zigbee.h 文件的內容。

程序清單 9.76 view_zigbee.h 文件內容

由此可見,當新增加 zigbee 視圖后,雖然與 LED 視圖不一樣,但可以共用同一個模型。

且 LED 視圖和布爾模型都不需要做任何修改,同時也沒有一行重復的視圖代碼,說明“用戶界面與內部實現(xiàn)”真正做到了分離。

3. MVC 應用

在 MVC 模式中,其核心是視圖接收來自模型和控制器的數(shù)據并決定如何顯示,控制器捕捉用戶的輸入事件和系統(tǒng)產生的事件。當控制器檢測到有鍵按下時,它將外部的事件轉換為內部的數(shù)據請求,控制器決定調用模型的那個函數(shù)進行處理,然后確定用那個視圖來顯示模型提供的數(shù)據,詳見程序清單 9.77。

程序清單 9.77 MVC 模式應用范例程序(main.c)

至此,實現(xiàn)了具有 LED 和 zigbee 兩個視圖的 MVC 應用程序,為了驗證 zigbee 視圖,實現(xiàn)遠程“監(jiān)控”,需要使用另外一個 zigbee 來接收 MVC 應用中 zigbee 視圖發(fā)出的數(shù)據“0”或“1”。為便于觀察,使用另外一塊 AM824ZB 開發(fā)板來接收數(shù)據,當接收到“0”時,其LED0 熄滅,當接收到“1”時,其 LED0 點亮,范例程序詳見程序清單 9.78。

程序清單 9.78 新增 AM84ZB 板用以接收 zigbee 數(shù)據的范例程序

在 MVC 應用中,zigbee 視圖將 zigbee 的本地地址設置為 0x2001,目標地址設置為0x2002,。新的 AM824ZB 開發(fā)板為了能夠接收到其發(fā)出的數(shù)據,需要對應的將本地地址設置為 0x2002,目標地址設置為 0x2001。

實際上,MVC 模式常用于處理 GUI 窗口事件,比如,每個窗口部件都是 GUI 相關事件的發(fā)布者,其它對象可以訂閱所關注的事件。比如,當按下 A 按鈕時,會發(fā)布相應的“動作事件”。另一個對象對這個按鈕進行注冊,便于在此按鈕按下時,得到相應的消息,然后完成某一動作。

由此可見,觀察者模式背后的思想等同于關注點分離原則背后的思想,其目的是降低發(fā)布者和訂閱者之間的耦合,便于在運行時動態(tài)地添加和刪除訂閱者。模式在抽象的原則和具體的實踐之間架起了一座橋梁,其主要動機是將變化帶來的影響局部化。

局部化影響的必然結果就是“捆綁邏輯和數(shù)據”,如果有可能盡量將其放在一個方法中,至少要放在一個對象里,最起碼也要放到一個包下面。在發(fā)生變化時,邏輯和數(shù)據很可能會同時被改動。如果將它們放在一起,那么修改它們所造成的的影響停留在局部。

其次,觀察者模式的最大推動力來自于 OCP 開放閉合原則,其動機就是為了在增加新的觀察者對象時,無需更改觀察對象,從而使觀察對象保持封閉,這對于系統(tǒng)的擴展性和靈活性有很大的提高。顯然由繼承實現(xiàn)的 OCP,使設計模式成為應變能力更強的工具。

>>> 9.3.6 MVC 應用程序優(yōu)化

在整個布爾模型的應用中,使用的硬件外設資源有 1 個按鍵、1 個 LED 和 zigbee 模塊,這些資源都有相應的可以跨平臺的通用接口。雖然程序清單 9.77 中絕大部分程序都沒有與硬件綁定,可以跨平臺復用,但是唯一的不足之處在于在應用程序中調用了實例初始化函數(shù)am_zm516x_inst_init(),而實例初始化函數(shù)是與平臺相關的,不同平臺可能不同,因此若實例初始化函數(shù)修改,則應用程序必須進行對應的修改。

顯然,實例初始化函數(shù)是初始化具體實例的,而應用程序并不關心具體實例,其只需要使用具體實例提供的通用服務(如 LED、zigbee、KEY)。基于此,將實例初始化函數(shù)的調用從應用程序中“分離”出去,應用程序全部使用通用接口實現(xiàn)。使用 LED,需要 LED 對應的 ID 號,使用按鍵,需要按鍵對應的編碼,使用 zigbee,需要 zigbee 的操作句柄,這些信息都可以通過參數(shù)傳遞。優(yōu)化后的應用程序范例詳見程序清單 9.79。

程序清單 9.79 應用程序實現(xiàn)(app_mvc_bool_main.c)

顯然,只需要準備好 1 個 LED、1 個按鍵和一個 zigbee 資源(調用它們對應的實例初始化函數(shù)),然后調用 app_mvc_bool_main()函數(shù)即可,為了便于調用 app_mvc_bool_main()函數(shù),將該函數(shù)聲明在 app_mvc_bool_main.h 中,詳見程序清單 9.80。

程序清單 9.80 應用程序入口函數(shù)聲明(app_mvc_bool_main.h)

在主程序中調用 app_mvc_bool_main()函數(shù)即可啟動應用,范例程序詳見程序清單 9.81。

程序清單 9.81 啟動應用程序(main.c)

注意,AM824ZB 板載的獨立按鍵 KEY1 和 LED 均在系統(tǒng)啟動時自動調用了實例初始化函數(shù),因此,無需再次調用。默認情況下,LED0 的 ID 為 0,KEY1 的按鍵編碼為 KEY_F1。

此時,若應用程序需要移動到其它硬件平臺上運行,或相關資源的 ID 發(fā)生變化,則只需要完善“啟動應用程序”這一部分代碼即可,其往往就是根據實際情況調用各個硬件實例的初始化函數(shù)。將資源的“準備”工作(初始化)從原先的應用程序中分離出來,使得應用程序徹底的通用化了,與具體硬件實現(xiàn)了完全的分離,可以靈活的跨平臺應用。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • ZigBee
    +關注

    關注

    158

    文章

    2270

    瀏覽量

    242738
  • 可編程邏輯
    +關注

    關注

    7

    文章

    515

    瀏覽量

    44083
  • 無線模塊
    +關注

    關注

    12

    文章

    622

    瀏覽量

    48491

原文標題:周立功:MVC 框架的應用

文章出處:【微信號:ZLG_zhiyuan,微信公眾號:ZLG致遠電子】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    一文了解嵌入式軟件開發(fā)的對象

    以前應用場景很單一,嵌入式開發(fā)可能談不上面向對象開發(fā)。但現(xiàn)在,做嵌入式開發(fā),沒有面向對象開發(fā),你就有點落伍了。 本文結合個人經驗和周立功《抽象接口技術和組件開發(fā)規(guī)范及其思想》,循
    的頭像 發(fā)表于 11-15 10:31 ?326次閱讀
    一文了解嵌入式軟件開發(fā)的<b class='flag-5'>對象</b>

    soc設計中的熱管理技巧

    ,提高性能,并減少能耗。 2. 熱設計原則SoC設計初期,就應該考慮熱設計原則,以減少熱問題的風險。這些原則包括: **功率分配:**合理分配S
    的頭像 發(fā)表于 11-10 09:34 ?272次閱讀

    TMS320x28xx eCAN的編程示例

    電子發(fā)燒友網站提供《TMS320x28xx eCAN的編程示例.pdf》資料免費下載
    發(fā)表于 10-18 11:51 ?0次下載
    TMS320x28xx eCAN的<b class='flag-5'>編程</b><b class='flag-5'>示例</b>

    TMS320C24x/C240x CAN的編程示例

    電子發(fā)燒友網站提供《TMS320C24x/C240x CAN的編程示例.pdf》資料免費下載
    發(fā)表于 10-17 09:30 ?0次下載
    TMS320C24x/C240x CAN的<b class='flag-5'>編程</b><b class='flag-5'>示例</b>

    掃描模塊的編程示例和調試策略

    電子發(fā)燒友網站提供《掃描模塊的編程示例和調試策略.pdf》資料免費下載
    發(fā)表于 09-27 09:38 ?0次下載
    掃描模塊的<b class='flag-5'>編程</b><b class='flag-5'>示例</b>和調試策略

    鴻蒙OS開發(fā):典型頁面場景【一次開發(fā),多端部署】實戰(zhàn)(設置典型頁面)

    示例展示了設置應用的典型頁面,其在小窗口和大窗口有不同的顯示效果,體現(xiàn)一次開發(fā)、多端部署的能力。
    的頭像 發(fā)表于 05-27 09:36 ?1141次閱讀
    鴻蒙OS開發(fā):<b class='flag-5'>典型</b>頁面場景【一次開發(fā),多端部署】實戰(zhàn)(設置<b class='flag-5'>典型</b>頁面)

    AMD Versal? Adaptive SoC CPM PCIE PIO EP設計CED示例

    本文可讓開發(fā)者們看懂 AMD Vivado Design Tool 2023.2 中的“AMD Versal Adaptive SoC CPM PCIE PIO EP 設計”CED 示例。?
    的頭像 發(fā)表于 05-10 09:39 ?570次閱讀
    AMD Versal? Adaptive <b class='flag-5'>SoC</b> CPM PCIE PIO EP設計CED<b class='flag-5'>示例</b>

    NoC DDRMC LPDDR4上運行AMD Versal? Adaptive SoC DCMAC設計示例

    注釋:默認 DCMAC 設計示例不包含 NoC DDRMC
    的頭像 發(fā)表于 04-24 09:44 ?800次閱讀
    NoC DDRMC LPDDR4上運行AMD Versal? Adaptive <b class='flag-5'>SoC</b> DCMAC設計<b class='flag-5'>示例</b>

    為什么很少用C++開發(fā)單片機

    C語言是面向過程的語言,C++是面向對象編程語言。結合本文來說,面向過程相比面向
    發(fā)表于 03-25 14:26 ?946次閱讀
    為什么很少用C++開發(fā)單片機

    英飛凌發(fā)布新型汽車可編程SoC

    英飛凌近期發(fā)布了搭載第五代人機界面(HMI)技術的新型汽車可編程SoC,以及汽車和工業(yè)級750V G1離散SiC MOSFET,這兩項新產品的發(fā)布進一步鞏固了英飛凌在半導體領域的領先地位。
    的頭像 發(fā)表于 03-08 10:52 ?803次閱讀

    plc梯形圖編程的基本原則

    PLC(可編程邏輯控制器)是現(xiàn)代自動化控制領域中廣泛應用的一種控制裝置。PLC的梯形圖編程是PLC控制中最常用的編程方式之一。本文將詳細介紹PLC梯形圖編程的基本
    的頭像 發(fā)表于 01-22 10:51 ?2490次閱讀

    YOLOv8實現(xiàn)旋轉對象檢測

    YOLOv8框架在在支持分類、對象檢測、實例分割、姿態(tài)評估的基礎上更近一步,現(xiàn)已經支持旋轉對象檢測(OBB),基于DOTA數(shù)據集,支持航拍圖像的15個類別對象檢測,包括車輛、船只、典型
    的頭像 發(fā)表于 01-11 10:43 ?1801次閱讀
    YOLOv8實現(xiàn)旋轉<b class='flag-5'>對象</b>檢測

    SDK在soc模式下,假如有一cv::Mat對象,應該如何將其轉變?yōu)閎m_image呢?

    使用的是3.0版本的SDK,程序執(zhí)行到該函數(shù)時,總是提示“未分配設備內存,不支持BMCV”,同時 bmcv_image_jpeg_enc 函數(shù)也因為相似的理由報錯。 請問,在soc模式下,假如有一
    發(fā)表于 01-10 06:28

    基于C/C++面向對象的方式封裝socket通信類流程簡析

    在掌握了基于 TCP 的套接字通信流程之后,為了方便使用,提高編碼效率,可以對通信操作進行封裝,本著有淺入深的原則,先基于 C 語言進行面向過程的函數(shù)封裝,然后再基于 C++ 進行面向對象
    的頭像 發(fā)表于 12-26 10:00 ?1814次閱讀

    基于C/C++面向對象的方式封裝socket通信類

    在掌握了基于 TCP 的套接字通信流程之后,為了方便使用,提高編碼效率,可以對通信操作進行封裝,本著有淺入深的原則,先基于 C 語言進行面向過程的函數(shù)封裝,然后再基于 C++ 進行面向對象
    的頭像 發(fā)表于 12-26 09:57 ?1332次閱讀
    主站蜘蛛池模板: 国产成人ae在线观看网站站| 白白操在线视频| 人人澡人人擦人人免费| 国模精品一区二区三区视频| 78m成人亚洲| 亚洲视频网站欧美视频网站| 亚洲AV久久无码精品九九软件| 肉小说高h| 老师小扫货水能么多叫出来| 高清国产在线播放成人| 99久久国产免费福利| 伊人久久精品线影院| 亚洲AV无码国产精品午夜久久| 欧美s00老人| 男人天堂999| 久热久热精品在线观看| 精品人妻伦九区久久AAA片69| 高h浪荡文辣文神奇宝贝| 99久久精品国内| 97蜜桃123| 99精品99| 扒开老师大腿猛进AAA片软件| 最新色导航| 亚洲精品成人a| 小草高清视频免费直播| 视频一区国产| 少妇仑乱A毛片| 亚洲AV无码专区国产精品麻豆| 偷窥wc美女毛茸茸视频| 亚洲国产AV精品卡一卡二| 亚洲精品黄色| 在线精品视频免费观看| 亚洲国产在线精品国偷产拍| 亚洲 欧美 日韩 国产 视频| 亚洲精品成人久久久影院| 永久免费在线视频| 99精品国产免费观看视频| 操他射他影院| 国产精品一区二区20P| 久久99国产精品二区不卡| 老师系列高H文|