C#面向对象——行为模式

十四、模板方法

                 动机:

                                   在面对一个算法或者结构完善且稳定,但是子步骤却面临着改变的情况,应该如何处理?

                 意图:

                                   定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。

                 结构:

                                           

                模板模式中的方法分为两类:

                               基本方法:由子类实现的方法,并且在模板方法被调用

                               模板方法:可以有一个或几个,一般是一个具体方法,也就是一个框架,实现对基本方法的调度,完成固定的逻辑

                模板方法的要点:

                               Template Method模式非常常见,在代码复用方面应用十分广泛。

                               实现类可以通过虚拟方法(基本方法)来改变框架的架构,也就是子类可以影响父类。

                               为了严谨起见,一般将虚拟方法(基本方法)设为protected

 

 十五、Command命令

                动机:

                        耦合是软件是否能应对变化的一个痛点,在软件构建过程中,“行为请求者”与“行为实现者”之间通常是紧耦合的关系,如何解决这种紧耦合关系?

                意图:

                        讲一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。

                结构:

                            

                Command模式的要点:

                           Command模式的根本目的在于将“行为请求者”与“行为实现者”解耦,也就是通过在两者之间添加一个抽象类,将两者剥离开来 

                           Command模式的扩展性很好,且不会带来较大的耦合,但也要注意过多的子类,会使command类特别臃肿。

                           Command模式与C#中的Delegate有些类似。但两者定义行为接口的规范有所区别:Command以面向对象中“接口——实现”来定义行为接口规范,更严格,更符合抽象原则;Delegate以函数签名来定义行为接口规范,更灵活,但抽象能力比较弱。

 

十六、解释器模式

                动机:

                           一个简单语法可以解释的场景

                           为了解决某些领域类似的模式,且有着较高频率的变化

                   意图:

                        给定一个语言,定义它的文法的一种表示,并定义一种解释器,这个解释器,这个解释器使用该表示来解释语言中的句子

                 结构:

                         

                 解释器模式的要点:

                             Interpreter模式有着较好的扩展性,可以应对复杂的变化,因此类的膨胀也不可避免。

                             Interpreter模式由于采用递归的方式,导致了一旦数据过大,或逻辑过于复杂必然导致效率的急剧下滑,所以该模式的应用是一个很大的问题,市面有很多现成的工具供我们使用,现成的优先使用

                             Interpreter模式由于其复杂性,不便于维护测试人员开展工作

 

 十七、中介者模式

                     动机:

                             在面对多个对象之间紧耦合的关系时,犹如理清一团乱线一般,不仅不便于阅读,而且也不方便管理,如何解决多个对象间的耦合关系

                     意图:

                             用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式的相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互

                      结构:

                               

                     Mediator模式的要点:

                                   将多个对象间复杂的关系解耦,由Mediator对对象间的逻辑关系集中管理,由“多个对象互相关联”转变为“多个对象和一个中介者关联”

                                   将多个对象转变为中介者模式后,同事类的增加,会导致中介者的逻辑关系愈加复杂

                                   Facade模式是解耦系统外到系统内(单向)的对象关联关系;Mediator模式是解耦系统内各个对象之间(双向)的关系

 

十八、Iterator迭代器

                      动机:

                              对于集合对象复杂多变的内部结构,不希望暴露给外界,同时又可以让客户代码透明地访问其中包含的元素

                      意图:

                              提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示

                      结构:

                          

                      Iterator迭代器的要点:

                                      访问一个聚合对象的内容而无需暴露它的内部表示

                                      为遍历不同的集合结构提供一个统一的接口,从而支持同样的算法在不同的集合结构上进行操作

                                      遍历的同时更改迭代器所在的集合结构,会导致问题

 

十九、Observer观察者

                        动机:

                                 一个对象的状态发生改变时,所有依赖的对象都将得到通知。这样的依赖关系过于紧密,如何将对象间的依赖关系弱化,建立松耦合的结构

                            意图:

                                 定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新

                        结构:

                                 

                        结构:

                                    使用面向对象的抽象,Observer模式使得我们可以独立地改变目标和观察者,从而使二者之间的依赖关系达至松耦合

                                    目标发送通知时,无需指定观察者,通知会自动传播。观察者自己决定是否需要订阅通知,目标对象对此一无所知

                                    一个被观察者,多个观察者,开发和调试就会比较复杂

 

二十、Chain of Responsibility 职责链

                          动机:

                                  一个请求可能被多个对象处理,但是一个请求只能被一个对象处理,如何直接指定对象的话,会造成请求和对象间的紧耦合

                          意图:

                                  使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递请求,直到又一条对象处理它为止

                           结构:

                                    

                                  

                          责任链模式的要点:

                                          一个请求可以由多个对象接受,但只能被一个对象处理,如果直接绑定请求和对象的话,必然产生紧耦合的关系,责任链的目的就是将两者解耦

                                          责任链可以通过扩展由自己来修改

                                          责任链可能到最后也没有一个合适的对象来处理,此时应该提前设置一个缺省机制来处理

                                          责任链的长度过长可能导致效率低下,类似递归的方式,在环节比较多的时候,调试的时候逻辑可能比较复杂

 

二十一、Memento备忘录

                             动机:

                                     某些对象的状态在转换过程中,可能由于某些需要,要求程序能够回溯到对象之前处于某个点时的状态。如果使用一些共有接口来让其他对象得到对象的状态,便会暴露对象的细节实现

                                            如何实现对象状态的良好保存于恢复?但同时又不会因此破坏对象本身的封装性。

                                  意图:

                                      在不破坏封装性的前提下,铺货一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将该对象恢复到保存的状态

                                  结构:

                                    

                           Memento模式的几个要点:

                                                备忘录存储原发器对象的内部状态,在需要时恢复原发器状态。Memento模式适用于“由原发器管理,却又必须存储在原发器之外的信息”

                                                在实现Memento模式中,要防止原发器以外的对象访问备忘录对象。备忘录对象有两个接口,一个为原发器使用的宽接口:一个为其他对象使用的窄接口

                                                在实现Memento模式时,要考虑拷贝对象状态的效率问题,如果对象开销比较大,可以采用某种增量式改变来改进Memento模式

 

二十二、状态模式

                         动机:

                                 某些对象的状态如果改变,其行为也会随之而发生改变,比如文档处于只读状态,其支持的行为和读写状态支持的行为就可能完全不同

                                 如何在运行时根据对象的状态来透明地更改对象的行为?而不会为对象操作和状态转化之间引入紧耦合?

                         意图:

                                 允许一个对象在其内部状态改变时改变它的行为。从而使对象看起来似乎修改了其行为。

                         结构:

                                  

                         State模式的要点:

                                            State模式将所有与一个特定状态相关的行为都放入一个State的子类对象中,在对象状态切换时,切换相应的对象;但同时维持State的接口,这样实现了具体操作与状态转化之间的解耦

                                             为了不同的状态引入不同的对象使得状态转换变得更加明确,而且可以保证不会出现状态不一致的情况,因为转换时原子性的——即要么彻底转换过来,要么不转换

                                             如果State对象没有实例变量,那么个上下文可以共享一个State对象,从而节省对象开销

 

二十三、Strategy策略模式

                             动机:

                                          某些对象使用的算法可能多种多样,经常改变,如果将这算法都编码到对象中,将会使对象变得异常复杂;而且有时候支持不适用的算法也是一个性能负担

                                          如何在运行时根据需要透明地改变对象的算法?将算法与对象本身解耦,从而避免这些问题

                             意图:

                                     定义一系列算法,把它们一个个封装起来,并且使它们可相互替换。该模式使得算法可独立于使用它的客户而改变

                             结构:

                                      

                             策略模式的要点:

                                                   Strategy及其子类为组件提供了一系列可重用的算法,从而可以使得类型在运行时方便地根据需要在各个算法之间进行切换。所谓封装算法,支持算法的变化

                                                   Strategy模式提供了用条件判断语句以外的另一种选择,消除条件判断语句,就是在解耦合。含有许多条件判断语句的代码通常都需要Strategy模式

                                                   与State类似,如果Strategy对象没有实例变量,那么各个上下文可以共享一个Strategy对象,从而节省对象开销

 

二十四、Visitor访问者模式

                              动机:

                                            由于需求的改变,某些类层次结构种常常需要增加新的行为,如果直接在基类种做这样的更改,将会给子类带来很繁重的变更负担,甚至破坏原有设计

                                            如何在不更改层次结构的前提下,在运动时根据需要透明地为类层级结构上的各个类动态添加新的操作,从而避免此类问题?

                              意图:

                                      表示一个作用与某对象结构种的各元素的操作。它可以在不改变各元素的类的前提下定义作用与这些元素的新的操作

                              结构:

                                       

                              Visitor模式的要点·:

                                                Visitor模式通过所谓双重分发来实现在不更改Element类层次结构的前提下,在运行时透明地为类层次结构上的各个类动态添加新的操作

                                                所谓双重分发即Visitor模式中间包括了两个多态分发;第一个为accept方法的多态辨析;第二个为visit方法的多态辨析

                                                Visitor模式的最大缺点在于扩展类层次架构,会导致Visitor类的改变。因此Vistor模式适用于“Element类层次结构稳定,而其中的操作却经常面临频繁改动”。

 

行为型模式:

               行为型模式包含11种设计模式,其中可分为“类行为模式”和“对象设计模式”,前者依靠继承实现的方式来实现行为,后者依靠对象间的组合和强大的算法逻辑实现行为。

               行为模式可以应对由简单到复杂的各种需求,复杂的需求可以由模式组合来实现。

posted @ 2021-02-26 22:19  刀锋2021  阅读(155)  评论(0编辑  收藏  举报