3中間件系統(tǒng)架構(gòu) 中間件系統(tǒng)作為一個軟件系統(tǒng)(或稱組件),在實現(xiàn)一定功能、性能要求之外,可理解性、可擴展性、可修改性(或稱可重構(gòu)性)、可插入性、可重用性等質(zhì)量屬性都將作為軟件設計的要求被提出來。
近十余年來,面向?qū)ο笏枷霂缀跞嬲碱I軟件設計領域,成為最主流的分析、設計方法。而近數(shù)年來,對設計模式的研究也已日臻完善,模式幾乎已成為一種“更高級編程語言”(相比于Java、C++等高級編程語言)被廣泛應用。
面向?qū)ο笏枷、設計模式都是以實現(xiàn)軟件的可理解、可擴展、可修改、可插入、可重用等目標為己任的,本文也將應用面向?qū)ο笏枷、參考模式語言,對中間件的軟件架構(gòu)做一個初步的探討,下文的例子如涉及高級編程語言,均采用Java語言[2]。
3.1封裝、隔離處理流程中的各個節(jié)點
將中間件的業(yè)務流程中的各個節(jié)點分作不同模塊處理,可以獲得封裝、高內(nèi)聚、低耦合等優(yōu)勢,參見圖5。
其中,報告上傳模塊,負責實現(xiàn)不同類型的報告上傳方式,如HTTP、JMS等;API接口模塊,負責隔離應用系統(tǒng)和中間件核心業(yè)務邏輯處理模塊,向應用系統(tǒng)提供中間件API接口;中間件核心業(yè)務邏輯處理模塊,負責中間件核心業(yè)務,包括數(shù)據(jù)接收過濾、數(shù)據(jù)分組、報告生成、規(guī)則對象的狀態(tài)跳轉(zhuǎn)等;閱讀器通信模塊,負責中間件系統(tǒng)與閱讀器的通信。
3.2門面模式、工廠模式對外部暴露API接口
為了避免后臺應用系統(tǒng),即中間件的客戶端過分耦合,采用門面模式(Facade)對系統(tǒng)內(nèi)部、外部實現(xiàn)清晰的隔離。處理流程可參見圖6所示的序列圖?蛻舳藘H僅與Facade類建立聯(lián)系,如果Facade接口定義得足夠清晰,客戶端可以對中間件的內(nèi)部實現(xiàn)一無所知,這體現(xiàn)了面向?qū)ο笾械姆庋b性。
類的設計參見源代碼示例,從中可以看出,采用簡單工廠模式(Simple Factory)能夠在客戶端不知情的情況下,靈活地替換API實現(xiàn)類的版本。中間件API接口清晰地定義了中間件提供的操作,客戶端只須知道工廠類(APIFactory)能夠得到中間件API接口的實例即可。
中間件API接口MiddlewareAPI:
publicinterfaceMiddlewareAPI{
void define(String specName, ECSpec spec);
void undefine(String specName);
void subscribe(String specName, String uri);
void unsubscribe(String specName, String uri);
EPCReports poll(String specName);
EPCReports immediate(ECSpec spec);
}
工廠類APIFactory:
publicclassAPIFactory{
publicstaticMiddlewareAPIgetAPIInstance(){
}
}
API的實現(xiàn)類A:
publicclassClient{
publicstaticvoidmain(String[] args) {
MiddlewareAPI api = APIFactory.getAPIInstance();
api.define("a new spec", new EPCSpec());
}
}
3.3狀態(tài)模式模擬規(guī)則的狀態(tài)機
規(guī)則在其生命周期中擁有不同的狀態(tài),在每個狀態(tài)對一系列操作都有著不同的表現(xiàn),于是可以利用狀態(tài)模式(state)來模擬規(guī)則的狀態(tài)機,將不同狀態(tài)的不同表現(xiàn)作為可變化因素封裝起來,參見代碼示例。
規(guī)則狀態(tài)接口ECState:
publicinterfaceECState{
voidsubscribe(StringspecName,String uri);
voidunsubscribe(StringspecName,String uri);
EPCReportspoll(StringspecName);
}
未被請求狀態(tài)類ECStateUnrequested:
publicclassECStateUnrequestedimplements ECState {
}
已被請求狀態(tài)類ECStateRequested:
publicclassECStateRrequestedimplements ECState {
}
激活狀態(tài)類ECStateActive:
publicclassECStateActiveimplements ECState {
}
規(guī)則類ECSpec:
publicclassECSpec{
privateECStatestate;
publicECStategetState(){
return state;
}
publicvoidsetState(ECStatestate) {
this.state = state;
}
}
這樣,在針對規(guī)則實施相應操作的時候,就可以直接把相應操作委派給其狀態(tài)屬性(ECState)去做即可。比如,ECSpec的subscribe操作,只需一行代碼“state.suscribe(specName, uri);”即可。其中,specName、uri為臨時變量,具體取值在方法調(diào)用之前確定。
由面向?qū)ο蟮亩鄳B(tài)性特征,根據(jù)state字段目前所指向的對象來動態(tài)確定由ECState接口的哪一個具體的實現(xiàn)類的代碼來完成工作。ECState接口的實現(xiàn)類根據(jù)實際情況確定是否需要在處理過程中修改ECSpec對象的狀態(tài)屬性(state),此處在應用狀態(tài)模式時,需要設計多個定時器類來輔助狀態(tài)機的跳轉(zhuǎn)[3]。
3.4策略模式切換多種報告上傳、命令下發(fā)方式
事件周期結(jié)束之后,中間件需要組裝報告上傳給規(guī)則的預訂者,即應用系統(tǒng)。上傳的方式有多種,如HTTP、Socket、JMS等等。中間件的核心邏輯處理模塊不應該關(guān)心具體的上傳技術(shù),相應工作應交給報告上傳模塊來做,核心邏輯處理模塊只須完成自己的工作,然后把一定格式的數(shù)據(jù)通過報告上傳模塊發(fā)送,參見代碼示例。
報告發(fā)送接口ReportSender:
publicinterfaceReportSender{
voidsendReport(ECReportsreports);
}
通過Http方式發(fā)送報告的ReportSender接口實現(xiàn)類ReportSenderByHttp:
publicclassReportSenderByHttpimplements ReportSender {
public void sendReport(ECReports reports) {
}
}
通過Socket方式發(fā)送報告的ReportSender接口實現(xiàn)類ReportSenderBySocket:
publicclassReportSenderBySocketimplements ReportSender {
publicvoidsendReport(ECReportsreports) {
}
}
通過JMS方式發(fā)送報告的ReportSender接口實現(xiàn)類ReportSenderByJms:
publicclassReportSenderByJmsimplements ReportSender {
publicvoidsendReport(ECReportsreports) {
}
}
報告發(fā)送示例客戶端類
SendReportWorker:
publicclassSendReportWorker{
privateReportSendersender;
privateECReportsreports;
publicvoidsetReports(ECReportsreports) {
this.reports = reports;
}
publicstaticvoidmain(String[] args) {
SendReportWorker worker = new
SendReportWorker();
worker.sender.sendReport(reports);
}
publicvoidsetSender(ReportSendersender) {
this.sender = sender;
}
}
這樣,發(fā)送消息的工人類可通過設置ReportSender的實例來靈活設置其發(fā)送方式。
同樣,中間件的清點命令下發(fā),即中間件與閱讀器之間的接口,也存在多種方式,如Socket、SOAP等,也可采用類似的設計。
3.5觀察者模式處理上報消息
閱讀器的消息上報轉(zhuǎn)換為消息對象,對消息對象的接收、分發(fā)可采用經(jīng)典的觀察者模式實現(xiàn)。