大雀软件园

首页 软件下载 安卓市场 苹果市场 电脑游戏 安卓游戏 文章资讯 驱动下载
技术开发 网页设计 图形图象 数据库 网络媒体 网络安全 站长CLUB 操作系统 媒体动画 安卓相关
当前位置: 首页 -> 技术开发 -> NET专区 -> Observer模式深度探索

Observer模式深度探索

时间: 2021-07-31 作者:daque

[简介]微软顶级本领巨匠jeffrey richter的大作,从来是阻挡相左的。为了扶助开拓者这篇专论observer形式的作品也不不同。observer形式是典范安排形式中运用最为普遍也最为精巧反复无常的形式之一。正文在.net本领框架下深刻暴露了observer形式的内在,犯得着细细品位。固然安排形式并不是全能丹,但真实是一个特殊宏大的东西,开拓职员或框架结构师可运用它主动地介入任何名目。安排形式可保证经过熟知和公认的处置计划处置罕见题目。形式生存的究竟普通在乎:大普遍题目,大概仍旧有其余部分或开拓小组处置过了。所以,形式供给了一种在开拓职员和构造之间共享可运用处置计划的情势。不管那些形式的根源是什么,那些形式都运用了大师所积聚的常识和体味。这可保证更快地开拓精确的代码,并贬低在安排或实行中展示缺点的大概性。其余,安排形式在工程小构成员之间供给了通用的术语。加入过巨型开拓项手段职员都领会,运用一组共通的安排术语和规则对胜利实行名目来说是至关要害的。最要害的是,即使能精确地运用,安排形式不妨俭朴您洪量的功夫。.net框架形式固然gof的示例仅限于c++和smalltalk,但安排形式并不与一定谈话或开拓平台绑缚在一道;microsoft .net框架的展示为领会安排形式供给了新的时机和情况。在框架类库(fcl)的开拓进程中,microsoft运用了很多gof形式。因为.net框架中供给的功效范畴特殊普遍,所以,还开拓和提出了少许崭新的形式。咱们对安排形式的接洽从observer形式动手。observer形式面向东西的开拓的一个主宰规则是,在给定的运用步调中精确地分别工作。体例中的每个东西该当将中心放在题目域中的分割笼统上。简而言之,一个东西只应做一件事,并且要将它做好。这种本领可保证在东西之间规定明显的范围,所以可供给更高的重用性和体例可保护性。一个更加要害的范围是用户界面和普通交易论理之间的交互。在运用步调的开拓进程中,须要赶快变动用户界面,而且不许对运用步调的其余局部爆发连带感化,这是不足为奇的事。其余,交易诉求也大概会爆发变革,而这十足与用户界面无干。具备充分开拓体味的人都领会,在很多情景下,这两组诉求城市爆发变革。即使没有分别ui和运用步调其余局部,窜改任一局部城市对完全形成倒霉的感化。很多运用步调都须要在用户界面和交易论理之间分别明显的范围。所以,自gui展示此后,很多面向东西的框架均扶助将用户界面从运用步调的其余局部中分别出来。个中的大局部运用步调沿用的安排形式简直沟通。这种形式常常称为查看者,它特殊无助于于在体例中百般东西之间分别明显的范围。其余,还会常常看到在框架或运用步调中与ui无干的局部中运用这种处置计划。observer形式的效率远远胜过了其首先的办法。论理模子固然observer形式有很反复无常体,但该形式的基础基础包括两个脚色:查看者(observer)和主体(subject)(熟习smalltalk mvc的人将那些术语辨别称为view和model)。在用户界面包车型的士情况中,查看者是控制向用户表露数据的东西。另一上面,主体表白从题目域中模仿的交易笼统。正如图第11中学所刻画的一律,在查看者和主体之间生存论理关系。当主体东西中爆发变动时,(比方,窜改范例变量),查看者就会查看这种变动,并相映地革新其表露。比方,假设咱们要开拓一种大略的运用步调,来盯梢全天的股票价钱。在此运用步调中,咱们指定一个stock类来模仿在nasdaq买卖的百般股票。该类包括一个范例变量,它表白在全天不同声段常常振动的股票价格。为了向用户表露此消息,运用步调运用一个stockdisplay类向stdout(规范输入)写消息。在此运用步调中,一个stock类范例动作主体,一个stockdisplay类范例动作查看者。跟着股票价格在买卖日中随功夫爆发变革,stock范例的暂时股票价格也会爆发变革(它还好吗变革并不要害)。由于stockdisplay范例正在查看stock范例,以是在那些状况爆发变革(窜改股票价格)时,就会向用户表露那些变革。经过运用这种查看进程,不妨在stock和stockdisplay类之间分别范围。假设运用步调的诉求第二天爆发变革,要运用鉴于窗体的用户界面。要起用此新功效,只须要结构一个新类stockform动作查看者。不管爆发什么情景,stock类都不须要举行任何窜改。究竟上,它以至不领会爆发该类变动。一致地,即使需要变革诉求stock类从另一个根源检索股票价格消息(大概是从web效劳,而不是从数据库中检索),则stockdisplay类不须要举行窜改。它不过连接查看stock就够了。物理模子正如大普遍处置计划一律,题目在乎详细。observer形式也不不同。固然论理模子规则查看者查看主体;但在实行这种形式时,这本质上是一个称呼滥用。更精确地说,查看者向主体备案,表白它查看主体的志愿。在那种状况爆发变革时,主体向查看者报告这种变革情景。当查看者不复蓄意查看主体时,查看者向主体撤消备案。那些办法辨别称为查看者备案、报告和撤消备案。大普遍框架经过回调来实行备案和报告。图2、3和4中所示的uml序列图模仿这种本领常常运用的东西和本领挪用。对于不熟习序列图的人来说,最上头的矩形框表白东西,而箭镞表白本领挪用。图2刻画了备案序列。查看者对主体挪用register本领,以将其自己动作参数传播。在主体收到此援用后,它必需将其保存起来,再不在未来某个功夫状况爆发变革时报告查看者。大普遍查看者实行并非将查看者援用径直保存在范例变量中,而是将此工作委派给一个独立的东西(常常为一个容器)。运用容器来保存查看者范例可供给特殊大的长处,咱们将对它举行扼要引见。图3超过表露了报告序列。当状况爆发变革时(askpricechanged),主体经过挪用get查看者s本领来检索容器中的一切查看者。主体而后列举检索的查看者,并挪用notify本领以报告查看者所爆发的状况变革。图4表露撤消备案序列。此序列是在查看者不复须要查看主体时实行的。查看者挪用unregister本领,并将其自己动作参数举行传播。而后,主体对容器挪用remove本领以中断查看进程。回到咱们的股票运用步调,让咱们领会一下备案和报告进程所爆发的感化。在运用步调启用进程中,一个stockdisplay类范例备案到stock范例中,并将其自己动作参数传播到register本领。stock范例(在容器中)生存对stockdisplay范例的援用。当股票价格属性爆发变革时,stock范例经过挪用notify本领向stockdisplay报告所爆发的变革。在运用步调封闭时,stockdisplay范例运用以次本领撤消备案stock范例:挪用unregister本领,中断两个范例之间的联系。请提防运用容器(而不是运用范例变量)来保存查看者援用有什么便宜。假设除暂时用户接口stockdisplay外,咱们还须要绘制股票价格在买卖日内变革的及时图形。为此,咱们创造了一个名为stockgraph的新类,它绘制股票价格(y轴)和当天功夫(x轴)的图形。在运用步调启用时,它同声在stock范例中备案stockdisplay和stockgraph类的范例。由于主体在容器(与范例变量对立)中保存查看者,以是这不会展示题目。当股票价格爆发变革时,stock范例向其容器中的两个查看者范例报告所爆发的状况变革。正如咱们所看到的一律,运用容器可供给更大的精巧性,即每个主体可扶助多个查看者。这使主体有大概向多数多个查看者报告所爆发的状况变革,而不是只报告一个查看者。固然不是强迫诉求,但很多框架为查看者和主体供给了一组要实行的接口。正如底下的c#代码示例所示,iobserver接口公然一种大众本领notify。此接口是由一切要用作查看者的类实行的。iobservable接口(是由一切要用作东体的类实行的)公然两种本领register和unregister。那些接口常常沿用笼统假造类或如实接口的情势(即使实行谈话扶助该类结构的话)。运用那些接口无助于于缩小查看者和主体之间的啮合联系。与查看者和主体类之间的精细啮合联系各别,iobserver和iobservable接口承诺实行独力于实行的操纵。经过对接口的领会,您将提防到键入的一切本领对准的是接口典型(与简直类对立)。这种本领将接口编制程序模子的便宜扩充到observer形式。iobserver和iobservable接口(c#)//interface the all observer classes should implementpublic interface iobserver { void notify(object anobject);}//iobserver//interface that all observable classes should implementpublic interface iobservable { void register(iobserver anobserver); void unregister(iobserver anobserver);}//iobservable再回到咱们的示例运用步调,咱们领会stock类用作东体。所以,它将实行iobservable接口。一致地,stockdisplay类实行iobserver接口。由于一切操纵都是由该接口设置的(而不是由简直类设置的),以是stock类并未与stockdisplay类绑定在一道,反之亦然。这使咱们不妨赶快地变动一定的查看者或主体实行,而不会影相应用步调的其余局部(运用各别的查看者替代stockdisplay或增添特殊的查看者范例)。除去那些接口外,框架还常常为主体供给一个通用基类,缩小了扶助observer形式所需的处事。基类实行iobservable接口,以供给扶助查看者范例保存和报告所需的普通构造。底下的c#代码示例扼要引见一个名为observableimpl的基类。纵然大概任何容器都不妨实行这一工作,但该类在register和unregister本领中将查看者保存委派给哈希表范例(为了简单起见,咱们在示例中运用哈希表动作容器,它只运用一个本领挪用来撤消备案一定的查看者范例)。还要提防增添了notifyobservers本领。此本领用来报告哈希表中保存的查看者。在挪用此本领时,将列举该容器,并对查看者范例挪用notify本领。observableimpl类(c#)//helper class that implements observable interfacepublic class observableimpl:iobservable { //container to store the observer instance (is not synchronized for this example) protected hashtable _observercontainer=new hashtable(); //add the observer public void register(iobserver anobserver){ _observercontainer.add(anobserver,anobserver); }//register //remove the observer public void unregister(iobserver anobserver){ _observercontainer.remove(anobserver); }//unregister //common method to notify all the observers public void notifyobservers(object anobject) { //enumeration the observers and invoke their notify method foreach(iobserver anobserver in _observercontainer.keys) { anobserver.notify(anobject); }//foreach }//notifyobservers}//observableimpl咱们的示例运用步调运用以次本领来运用此基类普通构造:窜改stock类以扩充observableimpl类,而不是供给其本人的一定iobservable接话柄现。由于observableimpl类实行了iobservable接口,以是不须要对stockdisplay类举行任何变动。本质上,这种本领简化了observer形式的实行,在维持类之间涣散啮合联系的同声,使多个主体反复运用沟通的功效。底下的.net查看者示例中心说领会iobservable和iobserver接口以及observablebase类在咱们的股票运用步调中的运用情景。除去stock和stockdisplay类外,此示例运用mainclass将查看者和主体范例关系起来,并窜改stock范例的askprice属性。此属性控制挪用基类的notifyobservers本领,而该本领又向该范例报告关系的状况变革。查看者示例(c#)//represents a stock in an applicationpublic class stock:observableimpl { //instance variable for ask price object _askprice; //property for ask price public object askprice { set { _askprice=value; base.notifyobservers(_askprice); }//set }//askprice property}//stock//represents the user interface in the applicationpublic class stockdisplay:iobserver { public void notify(object anobject){ console.writeline("the new ask price is:" + anobject); }//notify}//stockdisplaypublic class mainclass{ public static void main() { //create new display and stock instances stockdisplay stockdisplay=new stockdisplay(); stock stock=new stock(); //register the grid stock.register(stockdisplay); //loop 100 times and modify the ask price for(int looper=0;looper < 100;looper++) { stock.askprice=looper; } //unregister the display stock.unregister(stockdisplay); }//main}//mainclass.net框架中的observer形式鉴于咱们对observer形式的领会,让咱们将提防力转向此形式在.net框架中的运用情景。您们傍边特殊熟习fcl中所公然典型的人将会提防到,框架中没有iobserver、iobservable或observableimpl典型。固然您简直不妨在.net运用步调中运用那些结构,但引入委派和事变可供给新的、功效宏大的本领来实行observer形式,而不用开拓专用来扶助该形式的一定典型。究竟上,由于委派和事变是clr的头等分子,以是将此形式的基础结构增添到.net框架的中心中。所以,fcl在其构造中普遍运用observer形式。引见委派和事变里面处事办法的作品特殊多,咱们在此不复赘述。咱们只需证明委派是面向东西(和典型安定)版的因变量南针就够了。委派范例生存对范例或类本领的援用,承诺隐姓埋名挪用绑定本领。事变是在类上证明的特出结构,可在运转时颁布被关心东西的状况变革。事变表白咱们前方用来实行observer形式的备案、撤消备案和报告本领的情势笼统(clr和多种各别的编写翻译器对它供给扶助)。委派是在运转时备案到一定事变中的。在激励事变时,将挪用一切备案的委派,以使它们不妨收到事变的报告。依照observer形式设置的术语,证明事变的类即是主体。与咱们往日运用的iobservable接口和observableimpl类各别,主体类不须要实行给定接口或扩充基类。主体只须要公然一个事变,而不须要实行任何其余操纵。查看者创造的处事略多少许,但精巧性却普及得特殊多(咱们将在反面计划)。查看者并不实行iobserver接口和将其自己备案到主体中,而是必需创造一定的委派范例,并将此委派备案到主体事变中。查看者必需运用具备事变证明所指定典型的委派范例,要不,备案就会波折。在创造此委派范例的进程中,查看者将传播该主体向委派报告的本领(范例或静态)称呼。在将委派绑定到本领后,不妨将其备案到主体的事变中。一致地,也不妨从事变中撤消备案此委派。主体经过挪用事变向查看者供给报告。即使您不熟习委派和事变,则实行observer形式犹如须要做很多处事,更加是与咱们往日运用的iobserver和iobservable接口比拟。然而,它比听起来要大略少许,而且实行起来要简单得多。底下的c#和visual basic .net代码示例中心说领会在咱们的示例运用步调中扶助委派和事变所需的类窜改。提防,没有stock或stockdisplay类用来扶助该形式的任何基类或接口。运用委派和事变的查看者(c#)public class stock { //declare a delegate for the event public delegate void askpricedelegate(object aprice); //declare the event using the delegate public event askpricedelegate askpricechanged; //instance variable for ask price object _askprice; //property for ask price public object askprice { set { //set the instance variable _askprice=value; //fire the event askpricechanged(_askprice); } }//askprice property}//stock class//represents the user interface in the applicationpublic class stockdisplay { public void askpricechanged(object aprice) { console.write("the new ask price is:" + aprice + "\r\n"); }}//stockdispslay classpublic class mainclass { public static void main(){ //create new display and stock instances stockdisplay stockdisplay=new stockdisplay(); stock stock=new stock(); //create a new delegate instance and bind it //to the observer's askpricechanged method stock.askpricedelegate adelegate=new stock.askpricedelegate(stockdisplay.askpricechanged); //add the delegate to the event stock.askpricechanged+=adelegate; //loop 100 times and modify the ask price for(int looper=0;looper < 100;looper++) { stock.askprice=looper; } //remove the delegate from the event stock.askpricechanged-=adelegate; }//main}//mainclass在熟习了委派和事变后,您就会领会地看到它们的宏大后劲。与iobserver和iobservable接口以及observableimpl类各别,运用委派和事变可大大缩小实行此形式所需的处事量。clr和编写翻译器为查看者容器处置供给了普通,而且为备案、撤消备案和报告查看者供给了一个通用挪用商定。大概,委派的最大便宜是其不妨援用任何本领的固有个性(前提是它适合沟通的出面)。这承诺任何类用作查看者,而与它所实行的接口或它专用的类无干。固然运用iobserver和iobservable接口可缩小查看者和主体类之间的啮合联系,但运用委派可实足取消那些啮合联系。事变形式鉴于事变和委派,fcl不妨特殊普遍地运用observer形式。fcl的安排者充溢看法到此形式的宏大后劲,并在所有框架中将其运用于用户界面和非ui一定的功效。然而,用法与基础observer形式稍有各别,框架小组将其称为事变形式。常常,将此形式表白为事变报告过程中所波及的委派、事变和关系本领的正式定名商定。固然clr或规范编写翻译器并没有强迫诉求运用事变和委派的一切运用步调和框架都沿用这种形式,但microsoft倡导如许做。个中的第一公约定也大概是最要害的商定是主体公然的事变的称呼。对于它所表白的状况变革而言,此称呼该当是不言自明的。牢记,此商定以及一切其余该类商定自己即是主观性的。手段是为那些运用您的事变的职员供给明显的证明。事变形式的其余局部运用精确的事变定名,所以此办法对形式来说至关要害。回到咱们的示例,让咱们领会一下这种商定对stock类爆发的感化。派惹事件称呼的符合本领是,运用在主体类中窜改的字段的称呼动作根。由于在stock类中窜改的字段称呼是_askprice,以是有理的事变称呼该当是askpricechanged。很鲜明,此事变的称呼比statechangedinstockclass等具备更强的刻画性。所以,askpricechanged事变称呼适合第一公约定。事变形式中的第二公约定是精确定名委派及其出面。委派称呼该当包括事变称呼(经过第一个商定采用的)及附加词handler。此形式诉求委派指定两个参数,第一个参数供给对事变发送方的援用,第二个参数向查看者供给情况消息。第一个参数的称呼即是sender。必需将此参数键入为system.object。这是因为以次究竟:大概将委派绑定到体例中任何类上的任何潜伏本领。第二个参数的称呼(以至比第一个参数更大略)为e。必需将此参数键入为system.eventargs或那种派生类(偶尔比此实质还多)。固然委派的归来典型在于于您的实行须要,但大普遍实行此形式的委派基础不归来任何值。须要稍加提防委派的第二个参数e。此参数承诺主体东西将大肆情况消息传播给查看者。即使不须要该类消息,则运用system.eventargs范例就充满了,由于该类的范例表白没有情况数据。要不,该当运用相映的实行结构从system.eventargs派生的类以供给此数据。必需依照具备附加词eventargs的事变称呼来定名该类。请参考咱们的stock类,此商定诉求将处置askpricechanged事变的委派定名为askpricechangedhandler。其余,该当将此委派的第二个参数定名为askpricechangedeventargs。由于咱们须要将新的股票价格传播给查看者,以是咱们须要扩充system.eventargs类,以将该类定名为askpricechangedeventargs并供给实行来扶助传播此数据。事变形式中的结果一个商定是控制激励事变的主体类上本领的称呼和可考察性。此本领的称呼该当包括事变称呼以及增添的on前缀。该当将此本领的可考察性树立为养护。此商定仅实用于非密封(在vb中不行接受)类,由于它动作派生类挪用在基类中备案的查看者的已知的挪用点。将此结果一公约定运用于stock类,即可实行事变形式。由于stock类不是密封的,以是咱们必需增添一种本领来激励事变。依照该形式,此本领的称呼为onaskpricechanged。底下的c#代码示例表露运用于stock类的事变形式的完备视图。请提防咱们的system.eventargs类的特意用法。事变形式示例(c#)public class stock { //declare a delegate for the event public delegate void askpricechangedhandler(object sender, askpricechangedeventargs e); //declare the event using the delegatepublic event askpricechangedhandler askpricechanged; //instance variable for ask price object _askprice; //property for ask price public object askprice { set { //set the instance variable_askprice=value; //fire the eventonaskpricechanged(); } }//askprice property //method to fire event delegate with proper name protected void onaskpricechanged() { askpricechanged(this,new askpricechangedeventargs(_askprice)); }//askpricechanged }//stock class //specialized event class for the askpricechanged event public class askpricechangedeventargs:eventargs { //instance variable to store the ask price private object _askprice; //constructor that sets askprice public askpricechangedeventargs(object askprice) { _askprice=askprice; } //public property for the ask price public object askprice { get { return _askprice; } } }//askpricechangedeventargs论断鉴于这边对observer形式的领会,咱们不妨领会地看到此形式供给了一个完备的体制,不妨在运用步调中的东西之间规定明显的范围。固然经过回调举行实行(运用iobserver和iobservable接口)十分大略,但clr的委派和事变观念可处置大普遍“沉重的处事”,并贬低主体和查看者之间的啮合级别。本质上,经过精确地运用此形式,在保证运用步调可演化性上面就会向前迈出第一次全国代表大会步。当您的ui和交易诉求随功夫爆发变革时,observer形式可保证不妨简化您的处事。在开拓精巧的运用步调上面,安排形式是一个特殊宏大的东西(即使灵验地加以应用)。撰写正文是为了证明形式本领的灵验性,并中心证明.net框架中运用的一种形式。未来的作品将连接商量fcl中的形式,并扼要引见少许用来天生灵验web效劳的形式。

热门阅览

最新排行

Copyright © 2019-2021 大雀软件园(www.daque.cn) All Rights Reserved.