設(shè)計(jì)模式/軟件設(shè)計(jì)模式Oesign pattern)是軟件設(shè)計(jì)過(guò)程中的經(jīng)驗(yàn)總結(jié)???/span> 以讓程序代碼易重用、易理解、更穩(wěn)定。目前總結(jié)出來(lái)的模式有23種之多,文中主要涉及 “工廠模式”在多串口通信軟件開(kāi)發(fā)中的應(yīng)用。作者針對(duì)衡器稱重系統(tǒng)中常用的儀表、一機(jī)一
秤、一機(jī)多秤等應(yīng)用場(chǎng)景,提出相應(yīng)的解決方案。
1.引言
在軟件開(kāi)發(fā)過(guò)程中,常常會(huì)碰到相似問(wèn)題, 做重復(fù)的工作。如何提高效率,保證代碼的可靠 性,可重用性昵?前人總結(jié)出了很多軟件開(kāi)發(fā)模 式,來(lái)解決相應(yīng)的問(wèn)題。文中將針對(duì)“軟件設(shè)計(jì) 模式”一“工廠模式”在多串口通信軟件開(kāi)發(fā)中 的應(yīng)用展開(kāi)描述。
2.設(shè)計(jì)模式簡(jiǎn)介
設(shè)計(jì)模式(Oesign patten)是一套被反復(fù)使用 的、多數(shù)人知曉的、經(jīng)過(guò)分類編目的、代碼設(shè)計(jì) 經(jīng)驗(yàn)的總結(jié)。使用設(shè)計(jì)模式是為了重用代碼、讓 代碼更容易被他人理解、保證代碼可靠性。最早 提出設(shè)計(jì)模式思想是在1994年,由Erich Gamma 等人,在其所著的《面象對(duì)象的可復(fù)用元素》一 書(shū)中提出的??偨Y(jié)出三大類別創(chuàng)建型模式、結(jié) 構(gòu)型模式、行為型模式,六大原則(開(kāi)閉原則、 里氏原則、依賴倒置原則、接口隔離原則、迪米 特法則、合成復(fù)用原則,23種設(shè)計(jì)模式俱體內(nèi) 容請(qǐng)參看相關(guān)書(shū)籍。本文將重點(diǎn)介紹:工廠設(shè)計(jì) 模式。它屬于“創(chuàng)建型模式”,即在創(chuàng)建對(duì)象的過(guò) 程中,隱藏創(chuàng)建邏輯,這使得程序在創(chuàng)建給定實(shí) 例對(duì)象時(shí),可以提供靈活的判斷。
3.衡器軟件中的問(wèn)題
作者長(zhǎng)期從事衡器稱重軟件的設(shè)計(jì)。在長(zhǎng)期 的工作經(jīng)歷中,參與了很多項(xiàng)目,其中多數(shù)都會(huì) 用到串口通信。會(huì)遇到以下幾種典型的應(yīng)用問(wèn)題:
(1)在使用衡器儀表時(shí),串口是常見(jiàn)的對(duì)外通 信方式。稱重儀表廠家多,型號(hào)不一,通信格式 各不相同。能不能使用統(tǒng)一的開(kāi)發(fā)模式,進(jìn)行管 理,減少重復(fù)性的工作昵?
(2)地磅稱重管理中,有“一機(jī)一秤”,也有 機(jī)多秤”的模式。在多秤同時(shí)使用時(shí),儀表型 號(hào)可能相同,也可能不同,有沒(méi)有簡(jiǎn)潔、高效的 擴(kuò)展軟件代碼的方法昵?
4.工廠設(shè)計(jì)模式
針對(duì)上述問(wèn)題,作者通過(guò)實(shí)踐和總結(jié),覺(jué)得軟件開(kāi)發(fā)模式的中的“工廠模式”比較適合解決 這類問(wèn)題。
什么是“工廠模式”?顧名思義,就是客戶提 交“訂單”,交給“工廠”生產(chǎn),最后得到“產(chǎn) 品”。“工廠模式”模擬了這個(gè)過(guò)程。“工廠模 式”分為三種子類別:簡(jiǎn)單工廠、工廠方法、抽 象工廠。這三種方法,本質(zhì)相同,但各有其應(yīng)用 場(chǎng)景,簡(jiǎn)單來(lái)說(shuō),如下:
(1)簡(jiǎn)單工廠:一個(gè)工廠生產(chǎn)多種不同產(chǎn)品。
(2)工廠方法:多個(gè)工廠,每個(gè)工廠生產(chǎn)一種 產(chǎn)品。是對(duì)“簡(jiǎn)單工廠”的改進(jìn),因?yàn)?/span>“簡(jiǎn)單工 廠”不符合“開(kāi)閉原則”。
(3)抽象工廠:多個(gè)工廠,每個(gè)工廠生產(chǎn)一種 或多種產(chǎn)品??梢愿鶕?jù)“訂單”需求,生產(chǎn)“產(chǎn) 品”。“訂單”中可能存在多種不同的“產(chǎn)品”需 求,可以交給不同的“工廠”來(lái)“生產(chǎn)”。
這三種模式都能解決衡器軟件中的儀表串口 通信問(wèn)題。文中重點(diǎn)講解“簡(jiǎn)單工廠”和“抽象 工廠”這兩種模式,這兩種模式比較容易理解, 其它的模式也可依此類推。
5.面向?qū)ο蟮膶?shí)現(xiàn)過(guò)程
設(shè)計(jì)模式的運(yùn)用與編程語(yǔ)言無(wú)關(guān)。作者以常 用的C++語(yǔ)言為例,說(shuō)明面向?qū)ο蟮姆庋b過(guò)程。
首先,作者封裝了一組串口通信類,將串口 通信過(guò)程中,常用的的方法,封裝在一個(gè)類族里, 為后期模式設(shè)計(jì)提供基礎(chǔ)如圖1所示。
串口類庫(kù)可根據(jù)需要不斷擴(kuò)展,封裝好后, 與下文的設(shè)計(jì)模式類隔離,減少代碼耦合。這個(gè) 類族中的底層子類,相當(dāng)于“工廠”里生產(chǎn)的產(chǎn)品
(1)簡(jiǎn)單工廠的實(shí)現(xiàn)過(guò)程
簡(jiǎn)單工廠模式如圖2所示,將“產(chǎn)品”實(shí)例的創(chuàng)建放到工廠方法中完成,從而為“產(chǎn)品”的選擇提供靈活性。這里的“產(chǎn)品”就是儀表型號(hào),工廠就是 TMeterFactory 類,其方法 CreateMeter 可以創(chuàng)建各種儀表的實(shí)例。
主要部分的偽代碼如下:
#include
classTM eterfactory//儀表工廠類
{
Private:
m ap
TM eterfactory0;
ICommO bject*C reateM eter (char*strM eter- Name);//創(chuàng)建儀表實(shí)例方法
~TM eterFactoryO;//銷毀儀表類實(shí)例
};
ICommObject*TM eterFactory::CreateM eter (char*strM eterN am e)
{ //檢查儀表實(shí)例是否存在 ifm _m eter.end )!=m _m eter.find (strM eterN am e)) return m_m eter.find strM eterN am e)->second; //創(chuàng)建新的儀表實(shí)例 ICommO bject*pM eter=N ULL; if(!strcm p "X K 3190A 9",strM eterN am e)) pM eter=new TXK3190A9 0; else return NULL;
...//繼續(xù)添加代碼,創(chuàng)建其他儀表型號(hào) m_meter.insert std ^:pa ir
}
客戶端調(diào)用代碼如下: charweight[10]={0};
TMeterFactory*pFactory=new TMeterFactory;
ICommObject*pMeter=pFactory->CreateMe-
ter(“XK3190A9”);
strcpy(weight,pMeter->read());// 讀取重量,中間省略 open,write,close 等方法代碼
上述過(guò)程中,可以看到:在使用簡(jiǎn)單工廠模式 (或其它模式) 時(shí),并不一定能減少代碼量,但是易于后期擴(kuò)展和理解。從客戶端的調(diào)用代碼可以看出:模式提供了統(tǒng)一的接口,調(diào)用者只要給出儀表型號(hào),就能得到相應(yīng)的類實(shí)例。實(shí)例創(chuàng)建過(guò)程封裝到其他代碼塊中,只要那部分代碼沒(méi)有問(wèn)題,調(diào)用者就能得到正確的結(jié)果,相當(dāng)于黑盒操作。這種方式,適合多人分工合作,共同開(kāi)發(fā)軟件。
(2) 抽象工廠的實(shí)現(xiàn)過(guò)程
“簡(jiǎn)單工廠”模式適合“一機(jī)一秤”的稱重軟件開(kāi)發(fā)。“抽象工廠”模式適合解決“一機(jī)多秤”的稱重模式。他將儀表實(shí)例創(chuàng)建過(guò)程推遲到子類中完成,從而為“訂單”中的多種“產(chǎn)品”組合提供機(jī)會(huì)。以下是“一機(jī)一秤”和“一機(jī)兩秤”類圖如圖 3 所示。
由上圖可以看出,每一個(gè)“工廠”代表一種稱重模式,可以從“一機(jī)一秤”,擴(kuò)展到“一機(jī) n 秤”。而每一種稱重模式中,可以用同一種型號(hào)的儀表,也可以用不同種型號(hào)的儀表組成系統(tǒng)。具
體實(shí)施時(shí),可根據(jù)需求選擇。C++ 偽代碼如下: class ICommObject;
class IFactory // 抽象工廠
{
public:
virtual ICommObject * CreateMeter1()=0; // 創(chuàng)建儀表 1,此處為純虛方法
virtual ICommObject * CreateMeter2 ()=0; // 創(chuàng)建儀表 2
// 可以繼續(xù)添加 protected:
IFactroy();
};
Class TOne_pc_and_one_scale:public IFactory// 具體工廠:實(shí)現(xiàn)一機(jī)一秤功能
{
public:
ICommObject * CreateMeter1 () {return new TXK3190A9;}
};
Class TOne_pc_and_two_scale:public IFactroy// 具體工廠:實(shí)現(xiàn)一機(jī)兩秤功能
{
public:
ICommObject * CreateMeter1(){return new
T8142pro;}
ICommObject * CreateMeter2(){return new
XK3180;}
};
客戶端調(diào)用代碼如下: // 一機(jī)一秤調(diào)用方法
char weight_A9[10]={0};// 重量字符串
IFactory * pScale=new TOne_pc_and_one_scale;
ICommObject * pA9=pScale->CreateMeter1();
strcpy(weight,pA9->read());// 讀取重量到 weight
中,中間省略 open,write,close 等方法代碼
// 一機(jī)兩秤調(diào)用方法 char weight_8142[10]={0},weight_3180[10]={0};//
重量字符串
IFactory * pScale=new TOne_pc_and_two_scale; // 創(chuàng)建工廠實(shí)例
ICommObject * p3180=pScale->CreateMeter1(); ICommObject * p8142=pScale->CreateMeter2(); strcpy (weight_3180,p3180->read ());// 讀取重量
到 weight_A9 中,中間省略 open,write,close 等方法代碼
strcpy (weight_8142,p8142->read ()); // 讀取重量到 weight_814 中
使用“抽象工廠”模式,在添加新的“工廠”時(shí),并不影響已有的“工廠”代碼,已有的代碼基本不需改動(dòng),提高了程序的穩(wěn)定性,符合“開(kāi)
閉原則”,因此成為 23 種軟件設(shè)計(jì)模式之一。
6.工廠模式在稱重傳感器溫度測(cè)試軟件中的應(yīng)用
作者在編寫(xiě) 《傳感器溫度測(cè)試軟件》 的過(guò)程中,使用了數(shù)據(jù)采集板,每個(gè)板上有一個(gè)串口,多塊板同時(shí)向上位機(jī)發(fā)送傳感器的實(shí)時(shí)溫度測(cè)量數(shù)據(jù)。利用“抽象工廠設(shè)計(jì)”模式,很好的完成了軟件編寫(xiě)。原來(lái)在其他軟件中的通信代碼 (即圖 1),移植過(guò)來(lái)使用,進(jìn)行部分?jǐn)U展,實(shí)現(xiàn)了代碼重用。軟件可以對(duì)每一個(gè)串口的通信數(shù)據(jù)和通信參數(shù),進(jìn)行單獨(dú)的管理。如下圖:
7.相關(guān)問(wèn)題討論
在 Windows 系統(tǒng)中,某個(gè)“串口”設(shè)備,在某一時(shí)刻,只能被一個(gè)軟件使用 (虛擬串口設(shè)備除外)。多個(gè)進(jìn)程或線程同時(shí)使用,會(huì)產(chǎn)生沖突。沖突的情況分為三種:
(1) 兩個(gè) (或兩個(gè)以上) 不同的軟件,同時(shí)打開(kāi)同一個(gè)串口
(2) 同一個(gè)軟件,運(yùn)行兩次實(shí)例 (或兩次以上) 在內(nèi)存中,同時(shí)打開(kāi)同一個(gè)串口
(3) 同一個(gè)軟件,運(yùn)行一次,但在軟件內(nèi)部?jī)纱危ɑ騼纱我陨希?打開(kāi)同一個(gè)串口
①、②兩種情況涉及不同進(jìn)程之間的資源搶占的沖突,可以考慮用進(jìn)程互斥的方法解決,不屬于軟件模式的解決范疇。
對(duì)于第③種情況,可用“單例模式”解決軟件內(nèi)部多次、同時(shí)讀、寫(xiě)同一個(gè)串口沖突的問(wèn)題。
“單例模式”的目標(biāo)就是:每個(gè)類只能創(chuàng)建一個(gè)實(shí)例。類的“構(gòu)造函數(shù)”和“拷貝構(gòu)造函數(shù)”設(shè)為“私有”或“保護(hù)”權(quán)限,類實(shí)例由其靜態(tài)成員函數(shù)創(chuàng)建。
文中的“工廠模式”也涉及到串口的調(diào)用,因此可能有人會(huì)問(wèn):“工廠模式”能否結(jié)合“單例模式”同時(shí)使用呢?答案是否定的。“單例模式”封裝的對(duì)象是“串口”硬件實(shí)體。本文中的“工廠模式”是以“稱重儀表”為對(duì)象,進(jìn)行封裝。兩者的出發(fā)點(diǎn)和角度不同,雖然都用到了串口通信,但是功能需求不同。物理串口,同一時(shí)刻,只能被一個(gè)實(shí)例使用,因此用“單例模式”比較合理。而“稱重儀表”類,則存在多臺(tái)相同型號(hào)的儀表同時(shí)使用的情況,所以需要?jiǎng)?chuàng)建同一個(gè)類的多個(gè)實(shí)例。這些屬于面對(duì)的編程思想,需要結(jié)合實(shí)踐去體會(huì)他們的異同。
8.總結(jié)
在軟件設(shè)計(jì)過(guò)程中,不僅衡器稱重軟件“一機(jī)多秤”(即一臺(tái)上位機(jī),多臺(tái)稱重儀表同時(shí)工作),可以使用“工廠模式”來(lái)設(shè)計(jì),其它類似的—涉及多臺(tái)儀表,多個(gè)串口同時(shí)工作的軟件,都可參考這種模式。軟件模式的使用,使代碼易于閱讀,管理,能提高代碼的重用效率。實(shí)際軟件開(kāi)發(fā)中,具體使用哪種模式,是一種模式,還是多種模式混合使用?對(duì)于開(kāi)發(fā)者來(lái)說(shuō),需要有一定行業(yè)經(jīng)驗(yàn),總結(jié)出用戶的需求,整理出規(guī)律性的內(nèi)容,再選擇合適開(kāi)發(fā)模式,才能找到一條正確的道路。