摘要:介紹一種基于設(shè)計(jì)模式的儲(chǔ)層算法類庫(kù)中類間通信的框架模型,該框架模型將單件模式,觀察者模式應(yīng)用到設(shè)計(jì)和開發(fā)之中,使整個(gè)類庫(kù)的可復(fù)用性和可擴(kuò)展性有了很大的提高。
關(guān)鍵詞:算法類庫(kù);單件模式;觀察者模式;設(shè)計(jì)模式
中圖分類號(hào):TP311文獻(xiàn)標(biāo)識(shí)碼:A文章編號(hào):1009-3044(2010)03-733-03
Application of Design Patterns in Algorithm Class Library
WANG Jia-hua, ZHAO Zhi-bao
(School of Computer, Xi'an Shiyou University, Xi'an 710065, China)
Abstract: This paper describes the communication framework model of class in algorithm class library based on design pattern. The framework model applies singleton pattern and observer pattern to the design and development of class library, greatly improves reusability and scalability of algorithm class library.
Key words: algorithm class library; singleton pattern; observer pattern; design patterns
在儲(chǔ)層算法類庫(kù)設(shè)計(jì)中,類與類之間、界面類與用戶之間需要一種實(shí)時(shí)的通信方式。例如一個(gè)對(duì)象內(nèi)部狀態(tài)改變了,要及時(shí)通知監(jiān)測(cè)它的對(duì)象進(jìn)行響應(yīng);算法運(yùn)行時(shí),要向用戶提供算法運(yùn)行的進(jìn)度,算法的運(yùn)算的時(shí)間;算法界面對(duì)算法參數(shù)進(jìn)行設(shè)置時(shí),需要通知用戶算法參數(shù)是否出錯(cuò),為什么出錯(cuò)等等。本文主旨為通過(guò)面向?qū)ο蟪S玫脑O(shè)計(jì)模式設(shè)計(jì)實(shí)現(xiàn)一種易于擴(kuò)展、易于維護(hù)的類的通信模型,這對(duì)整個(gè)類庫(kù)的可復(fù)用性和可擴(kuò)展性都有顯著的提高。
1 儲(chǔ)層算法類庫(kù)的模式設(shè)計(jì)
面向?qū)ο蟮木幊讨校浖幊倘藛T更加注重以前的代碼的重用性和可維護(hù)性。設(shè)計(jì)模式使人們可以更加簡(jiǎn)單方便地復(fù)用成功的設(shè)計(jì)和體系結(jié)構(gòu)。將已證實(shí)的技術(shù)表述成設(shè)計(jì)模式也會(huì)使新系統(tǒng)開發(fā)者更加容易理解其設(shè)計(jì)思路。模式的好處在于:1)模式是以往一些專家解決問(wèn)題所留下的經(jīng)驗(yàn)經(jīng)過(guò)整理可以協(xié)助生手快速進(jìn)入設(shè)計(jì)程序的方式——這是經(jīng)驗(yàn)的結(jié)晶;2)模式可以容易的重復(fù)使用設(shè)計(jì)及結(jié)構(gòu)來(lái)開發(fā)新系統(tǒng);3)模式協(xié)助你選擇替代方案及改善維護(hù)工作。模式都是經(jīng)過(guò)實(shí)證且成功運(yùn)用在許多系統(tǒng)中;4)模式是前人的經(jīng)驗(yàn);學(xué)習(xí)模式可以避免我們?cè)僮哌^(guò)去失敗的過(guò)程。
1.1 通信模型的模式設(shè)計(jì)
本通信模型主要采用單件模式、觀察者模式。單件模式是創(chuàng)建型模式,主要是實(shí)例化一個(gè)類的對(duì)象,引入C++智能指針以后,可以通過(guò)智能指針引用計(jì)數(shù)管理對(duì)象內(nèi)存空間的釋放,有效避免C++語(yǔ)言內(nèi)存泄露的問(wèn)題。同時(shí)采用單件模式有以下好處:
1) 對(duì)唯一實(shí)例的受控訪問(wèn),讓類自身保存它的唯一實(shí)例。通常系統(tǒng)記錄報(bào)錯(cuò)類運(yùn)行時(shí)刻只有一個(gè)存在。
2) 可以保證客戶端沒(méi)有其他實(shí)例被創(chuàng)建,并提供一個(gè)訪問(wèn)該實(shí)例的方法。
3) 縮小名空間,對(duì)全局變量的一種改進(jìn)。它避免了那些存儲(chǔ)唯一實(shí)例的全局變量名污染名空間。
模型具體工作時(shí)采用觀察者模式。觀察者模式又叫做發(fā)布-訂閱(Publish/Subscribe)模式。觀察者模式定義了一種一對(duì)多地依賴模式,讓多個(gè)觀察者同時(shí)監(jiān)聽某一個(gè)主題對(duì)象。這個(gè)主題對(duì)象在狀態(tài)發(fā)生變化時(shí),會(huì)通知所有的觀察者對(duì)象,使它們能夠自動(dòng)更新自己。這里的主題對(duì)象就是指通知者,又叫做發(fā)布者。觀察者又叫訂閱者。一個(gè)軟件系統(tǒng)常常要求在某一個(gè)對(duì)象發(fā)生變化的時(shí)候,某些其它的對(duì)象做出相應(yīng)的改變,而觀察者模式是解決這個(gè)問(wèn)題的一個(gè)低耦合度的設(shè)計(jì)方案,它能夠減少對(duì)象之間的耦合以便更加利于系統(tǒng)的復(fù)用。
觀察者模式分兩種情況:
1) 拉模式,是目標(biāo)角色(subject)在發(fā)生變化后,僅僅告訴觀察者角色狀態(tài)發(fā)生變化了;觀察者角色如果想要知道具體的變化細(xì)節(jié),則就要自己從目標(biāo)角色的接口中得到。這種模式被很形象的稱為:拉模式——就是說(shuō)變化的信息是觀察者角色主動(dòng)從目標(biāo)角色中“拉”出來(lái)的。
2) 推模式,是目標(biāo)角色(subject)的“服務(wù)一條龍”,通知發(fā)生變化的同時(shí),通過(guò)一個(gè)參數(shù)將變化的細(xì)節(jié)傳遞到觀察者角色中去。這就是“推模式”——就是目標(biāo)角色主動(dòng)將變化的信息推給觀察者角色,不管觀察者需要不需要。具體設(shè)計(jì)模型如圖1所示。
1.2 核心類說(shuō)明
1) 抽象主題Subject(Channel):用于將所有的對(duì)象引用保存在一個(gè)聚集中(比如Vector對(duì)象)里,每個(gè)Subject可以有任何數(shù)量的觀察者。它又被叫做抽象觀察者(Observable)角色,一般使用抽象類或接口實(shí)現(xiàn)。
2) 抽象觀察者Observer(Scribe):為所有的具體觀察者定義一個(gè)接口,在得到Subject的通知時(shí)更新自己,在本模型中表現(xiàn)為Write純虛函數(shù)。
3) 具體主題ConcreteSubject (Log_channel等):將有關(guān)狀態(tài)存入具體觀察者對(duì)象。在具體主題的內(nèi)部狀態(tài)改變時(shí),給所有登記過(guò)的觀察者發(fā)出通知。又被稱為具體被觀察者角色。Error_channel是系統(tǒng)報(bào)錯(cuò)主題,Log_channel是系統(tǒng)日志記錄主題,Out_channel是Win32控制臺(tái)下輸出主題。每一個(gè)觀察者都可以訂閱一個(gè)或多個(gè)主題。在擴(kuò)展性方面,也可以根據(jù)實(shí)際需要定制特定情況的主題。
4) 具體觀察者ConcreteObserver(Void_notifer):實(shí)現(xiàn)了抽象觀察者Observer,在被觀察者發(fā)出通知時(shí),將自行執(zhí)行Update方法更新。在本模型實(shí)現(xiàn)中,具體觀察者可以訂閱多種主題,并根據(jù)不同的主題的通知進(jìn)行響應(yīng)。
1.3 程序?qū)崿F(xiàn)代碼
class Scribe : public Named_interface // 采用智能指針,Named_interface為智能指針管理類
{ public:
virtual ~Scribe() {} // 析構(gòu)函數(shù)
virtual bool subscribe(Channel channel); // 訂閱主題,將自己的引用指針存放在list中
virtual bool unsubscribe(Channel channel); // 解除訂閱,將自己的引用指針從list中刪除
virtual void write(const std::string str, const Channel* sender) = 0; //純虛函數(shù),子類實(shí)現(xiàn)
};
class Channel // 抽象主題類,定義主題共同擁有的屬性和操作
{ public:
Channel(); // 主題類構(gòu)造函數(shù)
virtual ~Channel(); // 主題類析構(gòu)函數(shù)
virtual bool attach(Scribe* scribe); // 增加觀察者,Scribe的subscribe調(diào)用attach進(jìn)行訂閱
virtual bool detach(Scribe* scribe); // 刪除觀察者,Scribe的unsubscribe調(diào)用attach進(jìn)行解除
virtual void send();// 向訂閱的觀察者發(fā)送狀態(tài)信息
protected:
std::ostringstream* buffer_; // 保存主題的狀態(tài)信息
std::list< SmartPtr
};
1.3.1 具體訂閱的過(guò)程
bool Channel::attach( Scribe* scribe )
{
scribes_.push_back( scribe ); // 具體的觀察者訂閱主題時(shí)把自己的引用加入觀察者列表中
return true;
}
bool Channel::detach( Scribe* scribe )
{
unsigned int size = scribes_.size();
scribes_.remove( SmartPtr
// 引用從觀察者列表中刪除
return scribes_.size() == size-1;
}
void Channel::send()
{
std::string message = buffer_->str();
if(message.empty()) return;
for( Channel::list_iterator it = scribes_.begin(); it != scribes_.end(); ++it)
{
(*it)->write( message, this ); // 觀察者實(shí)現(xiàn)自己wirte,為多態(tài)。
}
clear();
}
1.3.2 單件模式的實(shí)現(xiàn)
Log_channel* Log_channel::instance_ = 0; // 定義類靜態(tài)指針變量
Log_channel* Log_channel::instance() // 實(shí)例化指針變量,保證實(shí)例的唯一性
{
if(instance_ == 0)instance_ = new Out_channel;
return instance_;
}
2 結(jié)論與總結(jié)
通過(guò)設(shè)計(jì)模式中單件模式、觀察者模式兩者結(jié)合,一方面,可以很好的解決儲(chǔ)層算法類庫(kù)設(shè)計(jì)開發(fā)中算法實(shí)時(shí)報(bào)錯(cuò)、算法參數(shù)記錄、算法處理進(jìn)度顯示等問(wèn)題,同時(shí)在模型中加入智能指針、引用計(jì)數(shù)的技術(shù)管理對(duì)象的內(nèi)存空間的釋放,可以有效地避免內(nèi)存泄露問(wèn)題。另一方面,在解決實(shí)際問(wèn)題時(shí),也可以通過(guò)繼承Channel主題抽象類,定制符合實(shí)際要求的主題類,擴(kuò)展性強(qiáng)。
目前存在的問(wèn)題,是模型中智能指針在循環(huán)引用方面沒(méi)有解決,還需要進(jìn)一步的研究。
參考文獻(xiàn):
[1] 揣錦華,李軍民. C++程序設(shè)計(jì)語(yǔ)言[M]. 西安:西安電子科技大學(xué)出版社,2002.
[2] 藍(lán)雯飛. C++面向?qū)ο蟪绦蛟O(shè)計(jì)中的多態(tài)性研究[J]. 計(jì)算機(jī)工程與應(yīng)用,2002.
[3] (美)利普曼, 加·勞喬. C++ Primer中文版[M](第三版). 潘愛(ài)民, 張麗 譯. 北京:中國(guó)電力出版社,2002.
[4] 張龍祥.UML與系統(tǒng)分析設(shè)計(jì)[M]. 北京:人民郵電出版社,2007.
[5] Steven John Metsker. 設(shè)計(jì)模式j(luò)ava手冊(cè)[M]. 龔波,馮軍, 程群梅 譯.北京:機(jī)械工業(yè)出版社,2006.
[6] 周威.軟件設(shè)計(jì)模式的研究及其在影碟出租系統(tǒng)中的應(yīng)用[D]. 武漢:華中科技大學(xué)碩士學(xué)位論文,2007.