您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 咨询培训 > NETFramework中已使用的设计模式
2010年12月20日[Don'tbelieveinmagic!Understandwhatyourprogramdo,howtheydo!目标的坚定是性格中最必要的力量源泉之一,也是成功的利器之一。没有它,天才也会在矛盾无定的迷径中徒劳无功。]1.NET(C#)Internals:.NETFramework中已使用的设计模式2010-05-2920:01by吴秦,2234visits,网摘,收藏,编辑——适合有一定设计模式基础和.NET基础的人阅读。写在前面“设计模式”我一向是敬而远之的态度,不会去写这方面的文章,原因有二:第一,要想写好设计模式的文章太难,需要笔者丰富的经验;第二,没有深厚的功底写出的设计模式文章容易误导他人。自认没有深厚的功底,但我不会为了设计模式而设计模式。我想大部分人对设计模式的理解是不够深刻的,不然应用自如,特别是初学者!所有研究高质量的源码或框架是我们学习实践设计模式的好途径之一。而我之所以写这篇文章,主要是因为它从.NETFramework入手介绍已经使用的设计模式,作为一个.NET开发人员应该再熟悉不过了,能够有比较深刻的认识和理解。本文从.NETFramework中入手,发掘在.NETFramework中如何使用设计模式的。从中我们知道我们平时使用.NET时,我们使用了那些模式及学习使用设计模式。本文意译自DiscovertheDesignPatternsYou'reAlreadyUsinginthe.NETFramework及加入了相关设计模式的UML表示和主要介绍。主要内容如下:.NETFramework中使用的观察者模式(ObserverPattern).NETFramework中使用的迭代器模式(IteratorPattern).NETFramework中使用的装饰模式(DecoratorPattern).NETFramework中使用的适配器模式(AdapterPattern).NETFramework中使用的工厂模式(FactoryPattern).NETFramework中使用的策略模式(StrategyPattern)ASP.NET中的组合模式(CompositePattern).NETFramework中使用的模板方法模式(TemplateMethodPattern)ASP.NET管道中的模式(PatternsintheASP.NETPipeline)o截取过滤器模式(InterceptingFilterPattern)o页面控制器模式(PageControllerPattern)oASP.NET中的其它web表示模式(OtherWebPresentationPatternsinASP.NET)总结2010年12月20日[Don'tbelieveinmagic!Understandwhatyourprogramdo,howtheydo!目标的坚定是性格中最必要的力量源泉之一,也是成功的利器之一。没有它,天才也会在矛盾无定的迷径中徒劳无功。]21、观察者模式(ObserverPattern)观察者模式:在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常通过调用各观察者所提供的方法来实现。它的UML表示如下:图1、观察者模式的UML表示(来源:维基百科)好的面向对象设计都强调封装(encapsulation)和松耦合(loosecoupling)。换句话说,类应该保持内部细节私有并且最小化类之间严格的依赖关系。大部分应用程序,类并不是独立工作的,而是与其他类交互的。类交互的一个通常例子是:一个类应该(观察者,Observer)被通知,当被观察者(Subject)的某些东西改变了。例如,当单击一个按钮后可能某些WindowsForms的控件需要更新他们的显示。一个简单的解决方案是,当状态改变时让被观察者调用观察者特定的方法。但是,这回引入一连串的问题。因为被观察者需要知道调用哪个方法,这样就与特定观察者产生了紧耦合(tightcoupling)。而且,如果当需要添加多个观察者时,不得不继续添加每个观察者方法调用的代码。如果观察者的数量动态地改变,这将变得更复杂。这将很难维护!应用观察者模式能有效地解决这个问题。可以从观察者解耦被观察者,因此在设计时和运行时观察者可以容易地添加和移除。被观察者维护者一个对它感兴趣的观察者列表,每次被观察者的状态改变时,它对每个观察者调用Notify方法。下面这段代码展示了一个实现示例:viewsource2010年12月20日[Don'tbelieveinmagic!Understandwhatyourprogramdo,howtheydo!目标的坚定是性格中最必要的力量源泉之一,也是成功的利器之一。没有它,天才也会在矛盾无定的迷径中徒劳无功。]3print?01publicabstractclassCanonicalSubjectBase02{03privateArrayList_observers=newArrayList();04publicvoidAdd(ICanonicalObservero)05{06_observers.Add(o);07}08publicvoidRemove(ICanonicalObservero)09{10_observers.Remove(o);11}12publicvoidNotify()13{14foreach(ICanonicalObserveroin_observers)15{16o.Notify();17}18}19}2021publicinterfaceICanonicalObserver22{23voidNotify();24}所有的观察者类实现ICanonicalObserver接口,所有的被观察者必须继承自CanonicalSubjectBase。如果一个新的观察者想监视被观察者,Add方法可以轻松的处理而不必改变被观察者类的代码。注意:每个被观察者仅仅直接依赖于ICanonicalObserver接口,而不是特定的观察者。然而使用GOF的观察者模式解决这些问题仍有一些障碍,因为被观察者必须继承一个特定的基类且观察者必须实现一个特定接口。考虑回WindowsForms按钮的例子,.NETFramework引入了委托和事件来解决这些问题。如果你已经编写过2010年12月20日[Don'tbelieveinmagic!Understandwhatyourprogramdo,howtheydo!目标的坚定是性格中最必要的力量源泉之一,也是成功的利器之一。没有它,天才也会在矛盾无定的迷径中徒劳无功。]4ASP.NET或WindowsForms程序,你可能就是有了事件和事件处理器。事件作为被观察者,然而委托作为观察者。下面代码展示了使用事件的观察者模式:viewsourceprint?01publicdelegatevoidEvent1Hander();02publicdelegatevoidEvent2Handler(inta);0304publicclassSubject05{06publicSubject(){}07publicEvent1HanderEvent1;08publicEvent2HandlerEvent2;09publicvoidRaiseEvent1()10{11Event1Handlerev=Event1;12if(ev!=null)ev();13}1415publicvoidRaiseEvent2()16{17Event2Handlerev=Event2;18if(ev!=null)ev(6);19}20}2122publicclassObserver123{24publicObserver1(Subjects)25{26s.Event1+=newEvent1Hander(HandleEvent1);27s.Event2+=newEvent2Handler(HandleEvent2);28}29publicvoidHandleEvent1()2010年12月20日[Don'tbelieveinmagic!Understandwhatyourprogramdo,howtheydo!目标的坚定是性格中最必要的力量源泉之一,也是成功的利器之一。没有它,天才也会在矛盾无定的迷径中徒劳无功。]530{31Console.WriteLine(Observer1-Event1);32}33publicvoidHandleEvent2(inta)34{35Console.WriteLine(Observer1-Event2);36}37}WindowsFormsButton控件公开一个Click事件,当button被点击时产生。任何设计为响应这个事件的类仅需要用这个事件注册一个委托。Button类不依赖与任何潜在的观察者,并且每个观察者仅需要知道这个事件的委托的正确类型(这里是EventHandler)。因为EventHandler是一个委托类型而不是一个接口,每个观察者不需要实现一个额外的接口。假定它已经包含一个与签名兼容的方法,只需要用被观察者的事件注册方法。通过使用委托和事件,观察者模式使被观察者与观察者们之间解耦了。2、迭代器模式(IteratorPattern)迭代器模式:它可以让使用者通过特定的接口巡访容器中的每一个元素而不用了解底层的实作。它的UML表示如下:图2、迭代器模式的UML表示(来源:TerryLee的.NET设计模式(18):迭代器模式(IteratorPattern))2010年12月20日[Don'tbelieveinmagic!Understandwhatyourprogramdo,howtheydo!目标的坚定是性格中最必要的力量源泉之一,也是成功的利器之一。没有它,天才也会在矛盾无定的迷径中徒劳无功。]6许多编程任务包括操作对象的集合。不管这些集合是简单的列表还是更复杂的,如二叉树,经常需要访问集合中的每个对象。事实上,根据集合可能有几种不同的访问每个对象的方法,诸如从前向后、从后向前、前序或后序。为了保持集合简单,遍历代码通常放在自己单独的类中。存储一个对象列表的常用方法之一就是用数组。数组类型在VisualBasic.NET和C#中都是内置类型,他们都有一个循环结构用于在数组上迭代:foreach(C#)和ForEach(VisualBasic.NET)。下面是一个在数组上进行迭代的简单例子:viewsourceprint?1int[]values=newint[]{1,2,3,4,5};23foreach(intiinvalues)4{5Console.Write(i.ToString()+);6}这些语句在后台对数组使用了迭代器。我们需要知道的就是它保证了循环保证了对数组中的每个元素进行一次遍历。为了使这些语句起作用,foreach表达式中涉及的对象必须实现了IEnumerable接口。任何实现了IEnumerable接口的对象集合都可以被遍历(枚举)。这个接口仅有一个方法GetEnumerator(),它返回一个实现了IEnumerable的对象。IEnumerator接口包含遍历迭代集合所需要的代码,它有一个属性Current标识当前对象、方法MoveNext()移到下一个对象、方法Reset()重新开始。System.Collections命名空间中所有的集合类,及数组,都实现了IEnumerable接口,因此能被迭代。如果你测试了由C#编译器生成foreach的MSIL代码,你可以看到大部分情况它仅使用IEnumerator去做迭代(特定类型,如数组和字符串,由编译器特别处理)。下面代码展示用IEnumerator方法实现上例功能的代码:viewsourceprint?1int[]values=newint[]{1,2,3,4,5};2IEnumerator
本文标题:NETFramework中已使用的设计模式
链接地址:https://www.777doc.com/doc-2883881 .html