C语言C#设计模式之二十一访问者模式(Visitor Pattern)【行为型】

一、引言

  
今天我们初步说“行为型”设计模式的第九独模式,该模式是【访问者模式】,英文名称是:Visitor
Pattern。如果按照老,先由名称及来看看是模式,我向无克赢得任何针对晓该模式中之信息,而且以此模式在咱们的编码在被动用的连无是过多。该模式的用意定义格外虚幻,第一差看了这概念其实跟无看没什么分别,一头雾水,为了吃大家更好之知道该模式的初衷,我们举个例子来验证模式。比如:当我们为了缓解一个新的软件需要的时刻,经过差不多个日因为继夜的竭力,最终经过一个周到(自己觉得的)的软件设计解决了客户提出的初的急需,而且这个企划来周全的接近层次结构,并且是符合OO的规划原则的,我们格外开心,对协调计划的事物很有成就感。又过了一段时间,客户突然同时出了一个新的急需,需要呢依存的切近层次结构里面的近乎增加一个新的操作(其实就算是一个措施),怎么处置?好惩治,在面向OO设计模式中发生一个模式就是是为了化解此问题的,那就算是“访问者模式”,可以吧依存的好像层次结构中之切近轻松增加新的操作,我们延续吧,好好的问询一下欠模式。

老二、访问者模式之详细介绍

2.1、动机(Motivate)

  
在软件构建过程中,由于需要的转移,某些类层次结构中不时要增加新的所作所为(方法),如果直接在基类中召开这么的改变,将会晤受子类带来十分艰巨的更动负担,甚至破坏原有规划。如何在无重改类层次结构的前提下,在运作时根据需要透明地为接近层次结构上之逐条类动态增长新的操作,从而避免上述问题?

2.2、意图(Intent)

  
表示一个打算被有目标组织面临的依次要素的操作。它好当未改变各级要素的好像的前提下定义作用为这些要素的新的操作。                                     
——《设计模式》GoF

2.3、结构图(Structure)

     C语言 1

2.4、模式的结缘
    
    可以见到,在访问者模式之组织图有以下角色:

    (1)、抽象访问者角色(Vistor):
声明一个连多独访问操作,多个操作针对多单有血有肉节点角色(可以说有多少只具体节点角色就时有发生微访问操作),使得所有具体访问者必须贯彻的接口。

   
(2)、具体访问者角色(ConcreteVistor):实现抽象访问者角色中持有宣称的接口,也堪说凡是兑现对每个具体节点角色的新的操作。

   
(3)、抽象节点角色(Element):声明一个承受操作,接受一个访问者对象作为参数,如果产生外参数,可以当此“接受操作”里以概念相关的参数。

   
(4)、具体节点角色(ConcreteElement):实现抽象元素所确定之纳操作。

   
(5)、结构对象角色(ObjectStructure):节点的器皿,可以分包多个未同类或接口的器皿。

2.5、访问者模式的代码实现

   
访问者这个模式于咱们具体的编码在受到行使的并无是诸多,我哪怕直贴代码,让大家看代码的构造吧。今天于大家少个代码实例,自己逐渐体会访问者吧。实现代码如下:

  1 namespace Vistor
  2 {
  3     //抽象图形定义---相当于“抽象节点角色”Element
  4     public abstract class Shape
  5     {
  6         //画图形
  7         public abstract void Draw();
  8         //外界注入具体访问者
  9         public abstract void Accept(ShapeVisitor visitor);
 10     }
 11 
 12     //抽象访问者 Visitor
 13     public abstract class ShapeVisitor
 14     {
 15        public abstract void Visit(Rectangle shape);
 16 
 17        public abstract void Visit(Circle shape);
 18 
 19        public abstract void Visit(Line shape);
 20 
 21        //这里有一点要说:Visit方法的参数可以写成Shape吗?就是这样 Visit(Shape shape),当然可以,但是ShapeVisitor子类Visit方法就需要判断当前的Shape是什么类型,是Rectangle类型,是Circle类型,或者是Line类型。
 22     }
 23 
 24     //具体访问者 ConcreteVisitor
 25     public sealed class CustomVisitor:ShapeVisitor
 26     {
 27        //针对Rectangle对象
 28        public override void Visit(Rectangle shape)
 29        {
 30            Console.WriteLine("针对Rectangle新的操作!");
 31         }
 32        //针对Circle对象
 33        public override void Visit(Circle shape)
 34        {
 35            Console.WriteLine("针对Circle新的操作!");
 36        }
 37        //针对Line对象
 38        public override void Visit(Line shape)
 39        {
 40            Console.WriteLine("针对Line新的操作!");
 41        }
 42     }
 43  
 44     //矩形----相当于“具体节点角色” ConcreteElement
 45     public sealed class Rectangle: Shape
 46     {
 47         public override void Draw()
 48         {
 49             Console.WriteLine("矩形我已经画好!");
 50         }
 51 
 52         public override void Accept(ShapeVisitor visitor)
 53         {
 54            visitor.Visit(this);
 55          }
 56     }
 57  
 58     //圆形---相当于“具体节点角色”ConcreteElement
 59     public sealed class Circle:Shape
 60     {
 61         public override void Draw()
 62         {
 63             Console.WriteLine("圆形我已经画好!");
 64         }
 65 
 66         public override void Accept(ShapeVisitor visitor)
 67         {
 68             visitor.Visit(this);
 69          }
 70     }
 71  
 72     //直线---相当于“具体节点角色” ConcreteElement
 73     public sealed class Line:Shape
 74     {
 75         public override void Draw()
 76         {
 77             Console.WriteLine("直线我已经画好!");
 78         }
 79 
 80         public override void Accept(ShapeVisitor visitor)
 81         {
 82             visitor.Visit(this);
 83         }
 84     }
 85  
 86     //结构对象角色
 87     internal class AppStructure
 88     {
 89        private ShapeVisitor _visitor;
 90 
 91        public App(ShapeVisitor visitor)
 92        {
 93           this._visitor=visitor;
 94        }
 95 
 96        public void Process(Shape shape)
 97        {
 98           shape.Accept(_visitor)
 99        }
100     }
101 
102     class Program
103     {
104         static void Main(string[] args)
105         {
106             //如果想执行新增加的操作
107             ShapeVisitor visitor=new CustomVisitor();
108             AppStructure app=new AppStructure(visitor);
109 
110             Shape shape=new Rectangle();
111             shape.Draw();//执行自己的操作
112             app.Process(shape);//执行新的操作
113 
114 
115             shape=new Circle();
116             shape.Draw();//执行自己的操作
117             app.Process(shape);//执行新的操作
118 
119 
120             shape=new Line();
121             shape.Draw();//执行自己的操作
122             app.Process(shape);//执行新的操作
123             
124             
125             Console.ReadLine();
126         }
127     }
128 }

当即是访问者模式第二栽代码实例:

  1 namespace Visitor
  2 {
  3     //抽象访问者角色 Visitor
  4     public abstract class Visitor  
  5     {  
  6         public abstract void PutTelevision(Television tv);  
  7  
  8         public abstract void PutComputer(Computer comp);  
  9     }
 10 
 11     //具体访问者角色 ConcreteVisitor
 12     pubilc sealed class SizeVisitor : Visitor  
 13     {  
 14         public override void PutTelevision(Television tv)  
 15         {  
 16             Console.WriteLine("按商品大小{0}排放", tv.Size);  
 17         }  
 18  
 19         public override void PutComputer(Computer comp)  
 20         {  
 21             Console.WriteLine("按商品大小{0}排放", comp.Size);  
 22         }  
 23     }
 24 
 25     //具体访问者角色 ConcreteVisitor
 26     public sealed class StateVisitor : Visitor  
 27     {  
 28         public override void PutTelevision(Television tv)  
 29         {  
 30             Console.WriteLine("按商品新旧值{0}排放", tv.State);  
 31         }  
 32  
 33         public override void PutComputer(Computer comp)  
 34         {  
 35             Console.WriteLine("按商品新旧值{0}排放", comp.State);  
 36         }  
 37     }
 38 
 39     //抽象节点角色 Element
 40     public abstract class Goods  
 41     {  
 42         public abstract void Operate(Visitor visitor);
 43  
 44         private int nSize;  
 45         public int Size  
 46         {  
 47             get {return nSize;}  
 48             set {nSize = value;}  
 49         }
 50 
 51         private int nState;  
 52         public int State  
 53         {  
 54             get {return nState;}  
 55             set {nState = value;}  
 56         }  
 57      }
 58 
 59     //具体节点角色 ConcreteElement
 60     public sealed class Television : Goods  
 61     {  
 62         public override void Operate(Visitor visitor)  
 63         {  
 64             visitor.PutTelevision(this);  
 65         }  
 66     }  
 67  
 68     //具体节点角色 ConcreteElement
 69     pubic sealed class Computer : Goods  
 70     {  
 71         public override void Operate(Visitor visitor)  
 72         {  
 73             visitor.PutComputer(this);  
 74         }  
 75     }  
 76  
 77     //结构对象角色
 78     public sealed class StoragePlatform
 79     {  
 80         private IList<Goods> list = new List<Goods>();  
 81  
 82         public void Attach(Goods element)  
 83         {  
 84             list.Add(element);  
 85         }  
 86  
 87         public void Detach(Goods element)  
 88         {  
 89             list.Remove(element);  
 90         }  
 91  
 92         public void Operate(Visitor visitor)  
 93         {  
 94             foreach (Goods g in list)  
 95             {  
 96                 g.Operate(visitor);  
 97             }  
 98         }  
 99     }  
100  
101     class Program  
102     {  
103         static void Main(string[] args)  
104         {  
105             StoragePlatform platform = new StoragePlatform();  
106             platform.Attach(new Television());  
107             platform.Attach(new Computer());  
108  
109             SizeVisitor sizeVisitor = new SizeVisitor();  
110             StateVisitor stateVisitor = new StateVisitor();  
111  
112             platform.Operate(sizeVisitor);  
113             platform.Operate(stateVisitor);  
114  
115             Console.Read();  
116         }  
117     }  
118 }

其三、访问者模式的贯彻中心:

    Visitor模式通过所谓双重分发(double
dispatch)来兑现以匪重改Element类层次结构的前提下,在运作时透明地啊接近层次结构上的相继类动态增长新的操作。所谓双重分发即Visitor模式中包括了个别个多态分发(注意其中的多态机制):第一只呢accept方法的多态辨析;第二个也visit方法的多态辨析。

  设计模式其实是同种植堵漏洞的不二法门,但是尚未一样栽设计模式能够堵了所有的狐狸尾巴,即使是构成各种设计模式也是一致。每个设计模式都起漏洞,都有它们解决不了的动静或者变化。每一样种设计模式都设了某种变化,也只要了某种不弯。Visitor模式一旦的就算是操作变化,而Element类层次结构稳定。

    (1)、访问者模式之机要优点有:

       
1】、访问者模式让添加新的操作变得易。如果局部操作依赖让一个繁杂的布局对象的语,那么一般而言,添加新的操作会变得不得了复杂。而采用访问者模式,增加新的操作就表示加上一个初的访问者类。因此,使得添加新的操作变得好。

       
2】、访问者模式让有关的行操作集中到一个访问者对象吃,而无是散落到一个个之素看似吃。这点类似与”中介者模式”。

       
3】、访问者模式可看属于不同的等级结构的成员对象,而迭代只好看属于同一个品结构的积极分子对象。

 (2)、访问者模式之基本点缺点来:

       
1】、增加新的要素看似易得艰难。每多一个新的元素意味着要以空虚访问者角色中增一个初的肤浅操作,并在各个一个现实访问者类中上加相应的具体操作。具体来说,Visitor模式的最为深毛病在于扩大类层次结构(增添新的Element子类),会促成Visitor类的转。因此Visitor模式适用于“Element类层次结构稳定,而其中的操作却经常面临数转移”。

    (3)、在脚的情状下好考虑以访问者模式:

       
1】、如果系统发生比较稳定的数据结构,而同时有易于变化之算法时,此时得以设想动用访问者模式。因为访问者模式使算法操作的增长正如便于。

       
2】、如果同样组看似吃,存在在相似之操作,为了避免出现大量再的代码,可以设想把还的操作封装到访问者中。(当然为堪设想用抽象类了)

       
3】、如果一个目标在着有和自对象不相关联,或干比较弱的操作时,为了避免操作污染是目标,则足以考虑将这些操作封装到访问者对象吃。

季、.NET 访问者模式之落实

    
在现在的Net框架内,如果要是想叫现有的近乎增加新的办法,有了初的点子,那就是“扩展方法”,使用起来和实例方法是同同样的,而且在Net框架内,微软好呢刻画了累累之扩展方法为咱采取。我眼前还尚无读及Net的框架类库里面来“访问者模式”实现,看来好还欲努力,革命尚未成功啊。

五、总结

   
访问者模式写了了,这个模式刚开掌握起来或非常辛苦的,但是,如果我们大多扣几乎单实例代码,完全掌握也非是题材。随着C#言语的进步,设计模式里面的累累东西,我们可以通过C#语言的一部分表征做重新好之代表。我们描绘设计模式刚开头如逐渐来,一步一步的照猫画虎的来形容代码,等我们熟练掌握了模式之中心意思,我们且写符合C#作风与特点的模式代码了,或者说我们若就此C#来形容设计模式了,写出来的代码会再次精。