名称

Interpreter

结构

意图

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

适用性

  • 当有一个语言需要解释执行, 并且你可将该语言中的句子表示为一个抽象语法树时,可使用解释器模式。而当存在以下情况时该模式效果最好:
  • 该文法简单对于复杂的文法, 文法的类层次变得庞大而无法管理。此时语法分析程序生成器这样的工具是更好的选择。它们无需构建抽象语法树即可解释表达式, 这样可以节省空间而且还可能节省时间。
  • 效率不是一个关键问题最高效的解释器通常不是通过直接解释语法分析树实现的, 而是首先将它们转换成另一种形式。例如,正则表达式通常被转换成状态机。但即使在这种情况下, 转换器仍可用解释器模式实现, 该模式仍是有用的。

Code Example

namespace Interpreter_DesignPattern
{
    using System;
        using System.Collections;
 
        class Context 
        {
               
        }
 
        abstract class AbstractExpression 
        {
               abstract public void Interpret(Context c);
        }
 
        // class for terminal symbol
        class TerminalExpression : AbstractExpression
        {
               override public void Interpret(Context c)     
               {
                       
               }
        }
 
        // class for grammar rule (one per rule needed)
        class NonterminalExpression : AbstractExpression
        {
               override public void Interpret(Context c)     
               {
                       
               }       
        }
        // to extend grammar, just add other NonterminalExpression classes
 
        /// <summary>
    ///    Summary description for Client.
    /// </summary>
    public class Client
    {
        public static int Main(string[] args)
        {
                       Context c = new Context();
                       ArrayList l = new ArrayList(); //really need a tree here!
 
                       // build up context information 
                       // . . .
 
            // Populate abstract syntax tree with data
                       l.Add(new TerminalExpression());
                       l.Add(new NonterminalExpression());
 
                       // interpret
                       foreach (AbstractExpression exp in l)
                       {
                               exp.Interpret(c);
                       }
                       
            return 0;
        }
    }
}

名称

Template Method

结构

意图

定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。Te m p l a t e M e t h o d 使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

适用性

  • 一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。
  • 各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。这是O p d y k e 和J o h n s o n 所描述过的“重分解以一般化”的一个很好的例子[ O J 9 3 ]。首先识别现有代码中的不同之处,并且将不同之处分离为新的操作。最后,用一个调用这些新的操作的模板方法来替换这些不同的代码。
  • 控制子类扩展。模板方法只在特定点调用“h o o k ”操作(参见效果一节),这样就只允许在这些点进行扩展。

Code Example

namespace TemplateMethod_DesignPattern
{
    using System;
 
        class Algorithm 
        {
               public void DoAlgorithm() 
               {
                       Console.WriteLine("In DoAlgorithm");
                       
                       // do some part of the algorithm here
                       
                       // step1 goes here
                       Console.WriteLine("In Algorithm - DoAlgoStep1");                  
                       // . . . 
 
                       // step 2 goes here
                       Console.WriteLine("In Algorithm - DoAlgoStep2");                  
                       // . . . 
 
                       // Now call configurable/replacable part
                       DoAlgoStep3();
 
                       // step 4 goes here
                       Console.WriteLine("In Algorithm - DoAlgoStep4");                  
                       // . . . 
 
                       // Now call next configurable part
                       DoAlgoStep5();
               }
 
               virtual public void DoAlgoStep3()
               {
                       Console.WriteLine("In Algorithm - DoAlgoStep3");          
               }
 
               virtual public void DoAlgoStep5()
               {
                       Console.WriteLine("In Algorithm - DoAlgoStep5");                  
               }
        }
 
        class CustomAlgorithm : Algorithm
        {
               public override void DoAlgoStep3()
               {
                       Console.WriteLine("In CustomAlgorithm - DoAlgoStep3");
               }
 
               public override void DoAlgoStep5()
               {
                       Console.WriteLine("In CustomAlgorithm - DoAlgoStep5");
               }
        }
 
    /// <summary>
    ///    Summary description for Client.
    /// </summary>
    public class Client
    {
        public static int Main(string[] args)
        {
                       CustomAlgorithm c = new CustomAlgorithm();
 
                       c.DoAlgorithm();
 
            return 0;
        }
    }
}

 

名称

Chain of Responsibility

结构

意图

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

适用性

  • 有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定。
  • 你想在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
  • 可处理一个请求的对象集合应被动态指定。

Code Example

namespace ChainOfResponsibility_DesignPattern
{
    using System;
 
        abstract class Handler 
        {
               protected Handler successorHandler;
               abstract public void HandleRequest(Request request);       
               public void SetSuccessor(Handler sucessor)
               {
                       successorHandler = sucessor;
               }
        }
 
        class ConcreteHandler1 : Handler
        {
               override public void HandleRequest(Request request)
               {
                       // determine if we can handle the request
                       if (request.RequestType == 1) // some complex decision making!
                       {
                               // request handling code goes here
                               Console.WriteLine("request handled in ConcreteHandler1");
                       }
                       else 
                       {
                               // not handled here - pass on to next in the chain
                               if (successorHandler != null)
                                       successorHandler.HandleRequest(request);
                       }
               }
        }
 
        class ConcreteHandler2 : Handler
        {
               override public void HandleRequest(Request request)
               {
                       // determine if we can handle the request
                       if (request.RequestType == 2) // some complex decision making!
                       {
                               // request handling code goes here
                               Console.WriteLine("request handled in ConcreteHandler2");
                       }
                       else 
                       {
                               // not handled here - pass on to next in the chain
                               if (successorHandler != null)
                                       successorHandler.HandleRequest(request);
                       }
               }
        }
 
        class ConcreteHandler3 : Handler
        {
               override public void HandleRequest(Request request)
               {
                       // determine if we can handle the request
                       if (request.RequestType == 3) // some complex decision making!
                       {
                               // request handling code goes here
                               Console.WriteLine("request handled in ConcreteHandler3");
                       }
                       else 
                       {
                               // not handled here - pass on to next in the chain
                               if (successorHandler != null)
                                       successorHandler.HandleRequest(request);
                       }              
               }
        }
 
        class Request 
        {
               private int iRequestType;
               private string strRequestParameters;
 
               public Request(int requestType, string requestParameters)
               {
                       iRequestType = requestType;    
                       strRequestParameters = requestParameters;
               }
 
               public int RequestType 
               {
                       get 
                       {
                               return iRequestType;
                       }
                       set 
                       {
                               iRequestType = value;
                       }
               }
        }
 
    /// <summary>
    ///    Summary description for Client.
    /// </summary>
    public class Client
    {
        public static int Main(string[] args)
        {
            // Set up chain (usually one need to be done once)
                       Handler firstHandler = new ConcreteHandler1();
                       Handler secondHandler = new ConcreteHandler2();
                       Handler thirdHandler = new ConcreteHandler3();
                       firstHandler.SetSuccessor(secondHandler);
                       secondHandler.SetSuccessor(thirdHandler);
 
                       // After setting up the chain of responsibility, we can
                       // now generate requests and pass then off to the 
                       // chain to be handled
 
                       // generate and fire request
                       Request newRequest = new Request(2,"This are the request parameters");
                       firstHandler.HandleRequest(newRequest);
                       
            return 0;
        }
    }
}

 

名称

Command

结构

意图

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

适用性

  • 抽象出待执行的动作以参数化某对象,你可用过程语言中的回调(c a l l b a c k )函数表达这种参数化机制。所谓回调函数是指函数先在某处注册,而它将在稍后某个需要的时候被调用。C o m m a n d 模式是回调机制的一个面向对象的替代品。
  • 在不同的时刻指定、排列和执行请求。一个C o m m a n d 对象可以有一个与初始请求无关的生存期。如果一个请求的接收者可用一种与地址空间无关的方式表达,那么就可将负责该请求的命令对象传送给另一个不同的进程并在那儿实现该请求。
  • 支持取消操作。C o m m a n d 的E x c u t e 操作可在实施操作前将状态存储起来,在取消操作时这个状态用来消除该操作的影响。C o m m a n d 接口必须添加一个U n e x e c u t e 操作,该操作取消上一次E x e c u t e 调用的效果。执行的命令被存储在一个历史列表中。可通过向后和向前遍历这一列表并分别调用U n e x e c u t e 和E x e c u t e 来实现重数不限的“取消”和“重做”。
  • 支持修改日志,这样当系统崩溃时,这些修改可以被重做一遍。在C o m m a n d 接口中添加装载操作和存储操作,可以用来保持变动的一个一致的修改日志。从崩溃中恢复的过程包括从磁盘中重新读入记录下来的命令并用E x e c u t e 操作重新执行它们。
  • 用构建在原语操作上的高层操作构造一个系统。这样一种结构在支持事务( t r a n s a c t i o n )的信息系统中很常见。一个事务封装了对数据的一组变动。C o m m a n d 模式提供了对事务进行建模的方法。C o m m a n d 有一个公共的接口,使得你可以用同一种方式调用所有的事务。同时使用该模式也易于添加新事务以扩展系统。

Code Example

namespace Command_DesignPattern
{
    using System;
 
        abstract class Command 
        {
               abstract public void Execute();
               protected Receiver r;
               public Receiver R
               {
                       set 
                       {
                               r = value; 
                       }
               }
        }
 
        class ConcreteCommand : Command
        {
                override public void Execute()
               {
                       Console.WriteLine("Command executed");
                       r.InformAboutCommand();
               }
        }
 
        class Receiver 
        {
               public void InformAboutCommand()
               {
                       Console.WriteLine("Receiver informed about command");
               }
               
        }
 
        class Invoker 
        {
               private Command command;
               public void StoreCommand(Command c)
               {
                       command = c;
               }
               public void ExecuteCommand()
               {
                       command.Execute();
               }              
        }
 
        /// <summary>
    ///    Summary description for Client.
    /// </summary>
    public class Client
    {
        public static int Main(string[] args)
        {              
                       // Set up everything
                       Command c = new ConcreteCommand();
                       Receiver r = new Receiver();
                       c.R = r;
                       Invoker i = new Invoker();
                       i.StoreCommand(c);
 
                       // now let application run
 
                       // the invoker is how the command is exposed for the end-user 
                       // (or a client) initiates the command, 
                       // (e.g. toolbar button, menu item)
 
                       i.ExecuteCommand();
 
            return 0;
        }
    }
}

 

名称

Iterator

结构

意图

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

适用性

  • 访问一个聚合对象的内容而无需暴露它的内部表示。
  • 支持对聚合对象的多种遍历。
  • 为遍历不同的聚合结构提供一个统一的接口(即, 支持多态迭代)。

Code Example

namespace Iterator_DesignPattern
{
    using System;
        using System.Collections;
 
        class Node 
        {
               private string name;
               public string Name 
               {
                       get 
                       {
                               return name;   
                       }
               }
               public Node(string s)
               {
                       name = s;
               }
        }
        
        class NodeCollection 
        {
               private ArrayList list = new ArrayList();
               private int nodeMax = 0;
               
               // left as a student exercise - implement collection
               // functions to remove and edit entries also
               public void AddNode(Node n)
               {
                       list.Add(n); 
                       nodeMax++;                     
               }              
               public Node GetNode(int i)
               {
                       return ((Node) list[i]);
               }
 
               public int NodeMax 
               {                      
                       get 
                       {
                               return nodeMax;
                       }
               }
        }
 
        /*
         * The iterator needs to understand how to traverse the collection 
         * It can do that as way it pleases - forward, reverse, depth-first, 
         */
        abstract class Iterator 
        {
               abstract public Node Next();          
        }
 
        class ReverseIterator : Iterator
        {
               private NodeCollection nodeCollection;
               private int currentIndex;
 
               public ReverseIterator (NodeCollection c)
               {
                       nodeCollection = c;                   
                       currentIndex = c.NodeMax -1; // array index starts at 0!
               }
 
               // note: as the code stands, if the collection changes,
               // the iterator needs to be restarted 
               override public Node Next()
               {
            if (currentIndex == -1)
                               return null;
                       else 
                               return(nodeCollection.GetNode(currentIndex--));
               }
        }
        
    /// <summary>
    ///    Summary description for Client.
    /// </summary>
    public class Client
    {
        public static int Main(string[] args)
        {   
                       NodeCollection c = new NodeCollection();
                       c.AddNode(new Node("first"));
                       c.AddNode(new Node("second"));
                       c.AddNode(new Node("third"));
 
                       // now use iterator to traverse this
                       ReverseIterator i = new ReverseIterator(c);
 
                       // the code below will work with any iterator type
                       Node n;
                       do 
                       {
                               n = i.Next();
                               if (n != null) 
                                      Console.WriteLine("{0}", n.Name);
                       } while (n != null);
                               
            return 0;
        }
    }
}

 

 

名称

Mediator

结构

意图

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

适用性

  • 一组对象以定义良好但是复杂的方式进行通信。产生的相互依赖关系结构混乱且难以理解。
  • 一个对象引用其他很多对象并且直接与这些对象通信,导致难以复用该对象。
  • 想定制一个分布在多个类中的行为,而又不想生成太多的子类。

Code Example

namespace Mediator_DesignPattern
{
    using System;
 
        class Mediator 
        {
               private DataProviderColleague dataProvider;
               private DataConsumerColleague dataConsumer;
               public void IntroduceColleagues(DataProviderColleague c1, DataConsumerColleague c2)
               {
                       dataProvider = c1;
                       dataConsumer = c2;                    
               }
               
               public void DataChanged()
               {
                       int i = dataProvider.MyData;
            dataConsumer.NewValue(i);
               }
        }
 
        class DataConsumerColleague 
        {
               public void NewValue(int i)
               {
                       Console.WriteLine("New value {0}", i);
               }
        }
 
        class DataProviderColleague
        {
               private Mediator mediator;
               private int iMyData=0;
               public int MyData 
               {
                       get 
                       {
                               return iMyData;
                       }
                       set 
                       {
                               iMyData = value;
                       }
               }
               public DataProviderColleague(Mediator m)
               {
                       mediator = m;
               }
 
               public void ChangeData()
               {
                       iMyData = 403;
 
                       // Inform mediator that I have changed the data
                       if (mediator != null)
                               mediator.DataChanged();        
               }              
        }
 
    /// <summary>
    ///    Summary description for Client.
    /// </summary>
    public class Client
    {
        public static int Main(string[] args)
        {            
                       Mediator m = new Mediator();
                       DataProviderColleague c1 = new DataProviderColleague(m);
                       DataConsumerColleague c2 = new DataConsumerColleague();
                       m.IntroduceColleagues(c1,c2);
 
                       c1.ChangeData();
 
            return 0;
        }
    }
}

 

名称

Memento

结构

意图

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

适用性

  • 必须保存一个对象在某一个时刻的(部分)状态, 这样以后需要时它才能恢复到先前的状态。
  • 如果一个用接口来让其它对象直接得到这些状态,将会暴露对象的实现细节并破坏对象的封装性。

Code Example

namespace Memento_DesignPattern
{
    using System;
 
        class Originator 
        {
               private double manufacturer=0;
               private double distributor = 0;
               private double retailer = 0;
 
               public void MakeSale(double purchasePrice)
               {
                       // We assume sales are divided equally amount the three
                       manufacturer += purchasePrice * .40;
                       distributor += purchasePrice *.3;
                       retailer += purchasePrice *.3;
                       // Note: to avoid rounding errors for real money handling 
                       // apps, we should be using decimal integers
                       // (but hey, this is just a demo!)
               }
 
               public Memento CreateMemento()
               {
                       return (new Memento(manufacturer, distributor, retailer));                    
               }
               
               public void SetMemento(Memento m)
               {
                       manufacturer = m.A;
                       distributor = m.B;
                       retailer = m.C;
               }              
        }
 
        class Memento 
        {
               private double iA;
               private double iB;
               private double iC;
 
                public Memento(double a, double b, double c)
               {
                       iA = a;
                       iB = b;
                       iC = c;
               }
 
               public double A 
               {
                       get 
                       {
                               return iA;
                       }
               }
 
               public double B 
               {
                       get 
                       {
                               return iB;
                       }
               }
 
               public double C 
               {
                       get 
                       {
                               return iC;
                       }
               }
        }
 
        class caretaker 
        {
               
        }
 
            /// <summary>
    ///    Summary description for Client.
    /// </summary>
    public class Client
    {
        public static int Main(string[] args)
        {                      
                       Originator o = new Originator();
                       
                       // Assume that during the course of running an application 
                       // we we set various data in the originator
                       o.MakeSale(45.0);
                       o.MakeSale(60.0);
 
                       // Now we wish to record the state of the object
                       Memento m = o.CreateMemento();
 
                       // We make further changes to the object
                       o.MakeSale(60.0);
                       o.MakeSale(10.0);
                       o.MakeSale(320.0);
 
            // Then we decide ot change our minds, and revert to the saved state (and lose the changes since then)
                       o.SetMemento(m);
 
            return 0;
        }
    }
}

 

名称

Observer

结构

意图

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

适用性

  • 当一个抽象模型有两个方面, 其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。
  • 当对一个对象的改变需要同时改变其它对象, 而不知道具体有多少对象有待改变。
  • 当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之, 你不希望这些对象是紧密耦合的。

Code Example

namespace Observer_DesignPattern

{

    using System;

    using System.Collections;

 

        class Subject

        {

               private ArrayList list = new ArrayList();

 

               private string strImportantSubjectData = "Initial";

              

               public string ImportantSubjectData

                {

                       get

                       {

                               return strImportantSubjectData;

                       }

                       set

                       {

                               strImportantSubjectData = value;

                       }

               }

 

               public void Attach(Observer o)

               {

                       list.Add(o);

                       o.ObservedSubject = this;

               }

 

               public void Detach(Observer o)

               {

                      

               }

 

               public void Notify()

               {

                       foreach (Observer o in list)         

                       {

                               o.Update();

                       }                     

               }

        }

 

        class ConcreteSubject : Subject

        {

               public void GetState()

               {

                      

               }

 

               public void SetState()

               {

                      

               }      

        }

 

        abstract class Observer

        {

               protected Subject s;

               public Subject ObservedSubject

               {

                       get

                       {

                               return s;             

                       }

                       set

                       {

                               s = value;

                       }

               }      

               abstract public void Update();

        }

 

        class ConcreteObserver : Observer

        {

               private string observerName;

              

               public ConcreteObserver(string name)

               {

                       observerName = name;

               }

 

               override public void Update()

               {

                       Console.WriteLine("In Observer {0}: data from subject = {1}",

                               observerName, s.ImportantSubjectData);

               }      

        }

 

    /// <summary>

    ///    Summary description for Client.

    /// </summary>

    public class Client

    {    

        public static int Main(string[] args)

        {         

                       // Set up everything

                       ConcreteSubject s = new ConcreteSubject();

                       ConcreteObserver o1 = new ConcreteObserver("first observer");

                       ConcreteObserver o2 = new ConcreteObserver("second observer");

 

                       s.Attach(o1);

                       s.Attach(o2);

 

                       // make changes to subject

                       s. ImportantSubjectData = "This is important subject data";

 

                       // Notify all observers

                       s.Notify();                   

            return 0;

        }

    }

}

 

名称

State

结构

意图

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

适用性

  • 一个对象的行为取决于它的状态, 并且它必须在运行时刻根据状态改变它的行为。
  • 一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。这个状态通常用一个或多个枚举常量表示。通常, 有多个操作包含这一相同的条件结构。S t a t e模式将每一个条件分支放入一个独立的类中。这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。

Code Example

namespace State_DesignPattern
{
    using System;
 
        abstract class State 
        {
               protected string strStatename;        
 
               abstract public void Pour();
               // do something state-specific here
        }
 
        class OpenedState : State 
        {              
               public OpenedState ()
               {
                       strStatename = "Opened";
               }
               override public void Pour()
               {
                       Console.WriteLine("...pouring...");
                       Console.WriteLine("...pouring...");
                       Console.WriteLine("...pouring...");
               }
        }
        
        class ClosedState : State 
        {              
               public ClosedState()
               {
                       strStatename = "Closed";
               }
               override public void Pour()
               {
                       Console.WriteLine("ERROR - bottle is closed - cannot pour");
               }
        }
 
        class ContextColaBottle 
        {
               public enum BottleStateSetting {
                       Closed,
                       Opened
               };
 
               // If teh state classes had large amounts of instance data,
               // we could dynamically create them as needed - if this demo
               // they are tiny, so we just  create them as data members
               OpenedState openedState = new OpenedState();
               ClosedState closedState = new ClosedState();
 
               public ContextColaBottle ()
               {
                       // Initialize to closed
                       CurrentState = closedState;
               }
 
               private State CurrentState;
               
               public void SetState(BottleStateSetting newState)
               {
                       if (newState == BottleStateSetting.Closed)
                       {
                               CurrentState = closedState;
                       }
                       else 
                       {
                               CurrentState = openedState;
                       }
               }
 
               public void Pour()
               {
                       CurrentState.Pour();
               }       
        }
 
        /// <summary>
    ///    Summary description for Client.
    /// </summary>
    public class Client
    {
        public static int Main(string[] args)
        {
                       ContextColaBottle contextColaBottle = new ContextColaBottle();
 
                       Console.WriteLine("initial state is closed");
 
                       Console.WriteLine("Now trying to pour");
               contextColaBottle.Pour();
 
                       Console.WriteLine("Open bottle");
                       contextColaBottle.SetState(ContextColaBottle.BottleStateSetting.Opened);
 
                       Console.WriteLine("Try to pour again");
                       contextColaBottle.Pour();
 
            return 0;
        }
    }
}

 

名称

Strategy

结构

意图

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

适用性

  • 许多相关的类仅仅是行为有异。“策略”提供了一种用多个行为中的一个行为来配置一个类的方法。
  • 需要使用一个算法的不同变体。例如,你可能会定义一些反映不同的空间/时间权衡的算法。当这些变体实现为一个算法的类层次时[ H O 8 7 ] ,可以使用策略模式。
  • 算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构。
  • 一个类定义了多种行为, 并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入它们各自的S t r a t e g y 类中以代替这些条件语句。

Code Example

namespace Strategy_DesignPattern
{
    using System;
 
        
        abstract class Strategy 
        {
               abstract public void DoAlgorithm();
        }
 
        class FirstStrategy : Strategy 
        {
               override public void DoAlgorithm()
               {
                       Console.WriteLine("In first strategy");                     
               }
        }
 
        class SecondStrategy : Strategy 
        {
               override public void DoAlgorithm()
               {
                       Console.WriteLine("In second strategy");                    
               }
        }
 
        class Context 
        {
               Strategy s;
               public Context(Strategy strat)
               {
                       s = strat;                     
               }
 
               public void DoWork()
               {
                       // some of the context's own code goes here
               }
 
               public void DoStrategyWork()
               {
                       // now we can hand off to the strategy to do some 
                       // more work
                       s.DoAlgorithm();
               }
        }
 
    /// <summary>
    ///    Summary description for Client.
    /// </summary>
    public class Client
    {
        public static int Main(string[] args)
               {       
                       FirstStrategy firstStrategy = new FirstStrategy();
                       Context c = new Context(firstStrategy);
                       c.DoWork();
                       c.DoStrategyWork();
 
            return 0;
        }
    }
}

 

名称

Visitor

结构

意图

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

适用性

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

Code Example

namespace Visitor_DesignPattern
{
    using System;
 
        abstract class Visitor 
        {
               abstract public void VisitElementA(ConcreteElementA a);
               abstract public void VisitElementB(ConcreteElementB b);
        }
 
        class ConcreteVisitor1 : Visitor
        {
               override public void VisitElementA(ConcreteElementA a)
               {
                       
               }
 
               override public void VisitElementB(ConcreteElementB b)
               {
                       
               }
        }
 
        abstract class Element 
        {
               abstract public void Accept(Visitor v);
        }
 
        class ConcreteElementA : Element 
        {
               public Visitor myVisitor;
               override public void Accept(Visitor v)
               {
                       myVisitor = v;                 
               }
 
               public void OperationA()
               {
                       
               }
 
               public void DoSomeWork()
               {
                       // do some work here
                       // . . .
 
                       // Get visitor to visit
                       myVisitor.VisitElementA(this);        
 
                       // do some more work here
                       // . . .
               }
        }
 
        class ConcreteElementB : Element 
        {
               override public void Accept(Visitor v)
               {
                       
               }
 
               public void OperationB()
               {
                       
               }
        }
 
    /// <summary>
    ///    Summary description for Client.
    /// </summary>
    public class Client
    {
        public static int Main(string[] args)
        {                      
                       ConcreteElementA eA = new ConcreteElementA();
                       ConcreteElementB eB = new ConcreteElementB();
                       ConcreteVisitor1 v1 = new ConcreteVisitor1();
 
                       eA.Accept(v1);
                       eA.DoSomeWork();
 
            return 0;
        }
    }
}