设计模式24——行为型模式之访问者模式

定义:访问者模式(Vistor Pattern),表示一个作用于对象结构中各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

类型:对象行为型模式。

概述:

         访问者模式适用的场合比较狭窄,因为它的要求非常严。ConcreteElement要求具有一样的算法接口,并且ConcreteVisitor也要求一样的接口,这两点就使得访问者模式的使用范围比较窄。在《Head First Design Patterns》中也将访问者模式列为非常用模式之一。

          举一个例子,有一个仓库(对象结构),里面储存不同的电器(元素),如电视、电脑(具体元素),仓库可以按电器新旧或大小(具体的访问者)来摆放电器产品。

类图:


参与者:

  1. Client:构建抽象的访问者以及结构体对象。
  1. Storage,具体生成并存储不同的商品(如TelevisionComputer)。
  1. Goods,抽象商品类。
  2. TelevisionComputer,具体的商品类,对相应的属性完成赋值。
  1. Place,抽象的访问者类,提供抽象访问方法。
  1. StateSize,具体的访问者类,根据相应商品属性来实现具体的摆放方法Put()

示例代码:

[csharp] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Text;  
  4.   
  5. namespace Pattern24  
  6. {  
  7.     abstract class Visitor  
  8.     {  
  9.         public abstract void PutTelevision(Television tv);  
  10.   
  11.         public abstract void PutComputer(Computer comp);  
  12.     }  
  13.   
  14.     class SizeVisitor : Visitor  
  15.     {  
  16.         public override void PutTelevision(Television tv)  
  17.         {  
  18.             Console.WriteLine("按商品大小{0}排放", tv.Size);  
  19.         }  
  20.   
  21.         public override void PutComputer(Computer comp)  
  22.         {  
  23.             Console.WriteLine("按商品大小{0}排放", comp.Size);  
  24.         }  
  25.     }  
  26.   
  27.     class StateVisitor : Visitor  
  28.     {  
  29.         public override void PutTelevision(Television tv)  
  30.         {  
  31.             Console.WriteLine("按商品新旧值{0}排放", tv.State);  
  32.         }  
  33.   
  34.         public override void PutComputer(Computer comp)  
  35.         {  
  36.             Console.WriteLine("按商品新旧值{0}排放", comp.State);  
  37.         }  
  38.     }  
  39.   
  40.     abstract class Goods  
  41.     {  
  42.         public abstract void Operate(Visitor visitor);  
  43.         private int nSize;  
  44.         public int Size  
  45.         {  
  46.             get {return nSize;}  
  47.             set {nSize = value;}  
  48.         }  
  49.         private int nState;  
  50.         public int State  
  51.         {  
  52.             get {return nState;}  
  53.             set {nState = value;}  
  54.         }  
  55.      }  
  56.   
  57.     class Television : Goods  
  58.     {  
  59.         public override void Operate(Visitor visitor)  
  60.         {  
  61.             visitor.PutTelevision(this);  
  62.         }  
  63.     }  
  64.   
  65.     class Computer : Goods  
  66.     {  
  67.         public override void Operate(Visitor visitor)  
  68.         {  
  69.             visitor.PutComputer(this);  
  70.         }  
  71.     }  
  72.   
  73.     class Storage  
  74.     {  
  75.         private IList<Goods> list = new List<Goods>();  
  76.   
  77.         public void Attach(Goods element)  
  78.         {  
  79.             list.Add(element);  
  80.         }  
  81.   
  82.         public void Detach(Goods element)  
  83.         {  
  84.             list.Remove(element);  
  85.         }  
  86.   
  87.         public void Operate(Visitor visitor)  
  88.         {  
  89.             foreach (Goods e in list)  
  90.             {  
  91.                 e.Operate(visitor);  
  92.             }  
  93.         }  
  94.     }  
  95.   
  96.     class Program  
  97.     {  
  98.         static void Main(string[] args)  
  99.         {  
  100.             Storage storage = new Storage();  
  101.             storage.Attach(new Television());  
  102.             storage.Attach(new Computer());  
  103.   
  104.             SizeVisitor v1 = new SizeVisitor();  
  105.             StateVisitor v2 = new StateVisitor();  
  106.   
  107.             storage.Operate(v1);  
  108.             storage.Operate(v2);  
  109.   
  110.             Console.Read();  
  111.         }  
  112.     }  
  113. }  

适用性:

  1. 一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作。
  2. 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而你想避免让这些操作“污染”这些对象的类。
     Visitor
    使得你可以将相关的操作集中起来定义在一个类中。
     
    当该对象结构被很多应用共享时,用Visitor模式让每个应用仅包含需要用到的操作。
  1. 定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。
     
    改变对象结构类需要重定义对所有访问者的接口,这可能需要很大的代价。
     
    如果对象结构类经常改变,那么可能还是在这些类中定义这些操作较好                

优缺点:

  1. 优点,完成新的模板方法是不用修改原有代码,通过添加新代码完成。
  1. 缺点,当使用访问者模式时,打破了组合模式。

参考资料:

    1. 《设计模式——可复用面向对象软件基础》
    2. 《大话设计模式》
原文地址:https://www.cnblogs.com/feihe0755/p/3680799.html