.Net行为型设计模式之访问者模式(Visitor)

目录
  • 一、动机(Motivate)
  • 二、意图(Intent)
  • 三、结构图(Structure)
  • 四、模式的组成
  • 五、访问者模式的代码实现
  • 六、访问者模式的实现要点:
    • (1)、访问者模式的主要优点有:
    • (2)、访问者模式的主要缺点有:
    • (3)、在下面的情况下可以考虑使用访问者模式:
  • 七、.NET 访问者模式的实现

一、动机(Motivate)

在软件构建过程中,由于需求的改变,某些类层次结构中常常需要增加新的行为(方法),如果直接在基类中做这样的更改,将会给子类带来很繁重的变更负担,甚至破坏原有设计。如何在不更改类层次结构的前提下,在运行时根据需要透明地为类层次结构上的各个类动态添加新的操作,从而避免上述问题?

二、意图(Intent)

表示一个作用于某对象结构中的各个元素的操作。它可以在不改变各元素的类的前提下定义作用于这些元素的新的操作。                                 ——《设计模式》GoF

三、结构图(Structure)

四、模式的组成

可以看出,在访问者模式的结构图有以下角色:
(1)、抽象访问者角色(Vistor): 声明一个包括多个访问操作,多个操作针对多个具体节点角色(可以说有多少个具体节点角色就有多少访问操作),使得所有具体访问者必须实现的接口。
(2)、具体访问者角色(ConcreteVistor):实现抽象访问者角色中所有声明的接口,也可以说是实现对每个具体节点角色的新的操作。
(3)、抽象节点角色(Element):声明一个接受操作,接受一个访问者对象作为参数,如果有其他参数,可以在这个“接受操作”里在定义相关的参数。
(4)、具体节点角色(ConcreteElement):实现抽象元素所规定的接受操作。
(5)、结构对象角色(ObjectStructure):节点的容器,可以包含多个不同类或接口的容器。

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

访问者这个模式在我们现实的编码生活中使用的并不是很多,我就直接贴代码,让大家看代码的结构吧。今天给大家两个代码实例,自己慢慢体会访问者吧。实现代码如下:

static void Main(string[] args)
{
    //如果想执行新增加的操作
    ShapeVisitor visitor = new CustomVisitor();
    AppStructure app = new AppStructure(visitor);

    Shape shape = new Rectangle();
    shape.Draw();//执行自己的操作
    app.Process(shape);//执行新的操作

    shape = new Circle();
    shape.Draw();//执行自己的操作
    app.Process(shape);//执行新的操作

    shape = new Line();
    shape.Draw();//执行自己的操作
    app.Process(shape);//执行新的操作

}

//抽象图形定义---相当于“抽象节点角色”Element
public abstract class Shape
{
    //画图形
    public abstract void Draw();
    //外界注入具体访问者
    public abstract void Accept(ShapeVisitor visitor);
}

//抽象访问者 Visitor
public abstract class ShapeVisitor
{
    public abstract void Visit(Rectangle shape);

    public abstract void Visit(Circle shape);

    public abstract void Visit(Line shape);

    //这里有一点要说:Visit方法的参数可以写成Shape吗?就是这样 Visit(Shape shape),当然可以,但是ShapeVisitor子类Visit方法就需要判断当前的Shape是什么类型,是Rectangle类型,是Circle类型,或者是Line类型。
}

//具体访问者 ConcreteVisitor
public sealed class CustomVisitor : ShapeVisitor
{
    //针对Rectangle对象
    public override void Visit(Rectangle shape)
    {
        Console.WriteLine("针对Rectangle新的操作!");
    }
    //针对Circle对象
    public override void Visit(Circle shape)
    {
        Console.WriteLine("针对Circle新的操作!");
    }
    //针对Line对象
    public override void Visit(Line shape)
    {
        Console.WriteLine("针对Line新的操作!");
    }
}

//矩形----相当于“具体节点角色” ConcreteElement
public sealed class Rectangle : Shape
{
    public override void Draw()
    {
        Console.WriteLine("矩形我已经画好!");
    }

    public override void Accept(ShapeVisitor visitor)
    {
        visitor.Visit(this);
    }
}

//圆形---相当于“具体节点角色”ConcreteElement
public sealed class Circle : Shape
{
    public override void Draw()
    {
        Console.WriteLine("圆形我已经画好!");
    }

    public override void Accept(ShapeVisitor visitor)
    {
        visitor.Visit(this);
    }
}

//直线---相当于“具体节点角色” ConcreteElement
public sealed class Line : Shape
{
    public override void Draw()
    {
        Console.WriteLine("直线我已经画好!");
    }

    public override void Accept(ShapeVisitor visitor)
    {
        visitor.Visit(this);
    }
}

//结构对象角色
internal class AppStructure
{
    private ShapeVisitor _visitor;

    public AppStructure(ShapeVisitor visitor)
    {
        this._visitor = visitor;
    }

    public void Process(Shape shape)
    {
        shape.Accept(_visitor);
    }
}

这是访问者模式第二种代码实例:

static void Main(string[] args)
{
    StoragePlatform platform = new StoragePlatform();
    platform.Attach(new Television());
    platform.Attach(new Computer());

    SizeVisitor sizeVisitor = new SizeVisitor();
    StateVisitor stateVisitor = new StateVisitor();

    platform.Operate(sizeVisitor);
    platform.Operate(stateVisitor);
}
//抽象访问者角色 Visitor
public abstract class Visitor
{
    public abstract void PutTelevision(Television tv);

    public abstract void PutComputer(Computer comp);
}

//具体访问者角色 ConcreteVisitor
public sealed class SizeVisitor : Visitor
{
    public override void PutTelevision(Television tv)
    {
        Console.WriteLine("按商品大小{0}排放", tv.Size);
    }

    public override void PutComputer(Computer comp)
    {
        Console.WriteLine("按商品大小{0}排放", comp.Size);
    }
}

//具体访问者角色 ConcreteVisitor
public sealed class StateVisitor : Visitor
{
    public override void PutTelevision(Television tv)
    {
        Console.WriteLine("按商品新旧值{0}排放", tv.State);
    }

    public override void PutComputer(Computer comp)
    {
        Console.WriteLine("按商品新旧值{0}排放", comp.State);
    }
}

//抽象节点角色 Element
public abstract class Goods
{
    public abstract void Operate(Visitor visitor);

    private int nSize;
    public int Size
    {
        get { return nSize; }
        set { nSize = value; }
    }

    private int nState;
    public int State
    {
        get { return nState; }
        set { nState = value; }
    }
}

//具体节点角色 ConcreteElement
public sealed class Television : Goods
{
    public override void Operate(Visitor visitor)
    {
        visitor.PutTelevision(this);
    }
}

//具体节点角色 ConcreteElement
public sealed class Computer : Goods
{
    public override void Operate(Visitor visitor)
    {
        visitor.PutComputer(this);
    }
}

//结构对象角色
public sealed class StoragePlatform
{
    private IList<Goods> list = new List<Goods>();

    public void Attach(Goods element)
    {
        list.Add(element);
    }

    public void Detach(Goods element)
    {
        list.Remove(element);
    }

    public void Operate(Visitor visitor)
    {
        foreach (Goods g in list)
        {
            g.Operate(visitor);
        }
    }
}

六、访问者模式的实现要点:

Visitor模式通过所谓双重分发(double dispatch)来实现在不更改Element类层次结构的前提下,在运行时透明地为类层次结构上的各个类动态添加新的操作。所谓双重分发即Visitor模式中间包括了两个多态分发(注意其中的多态机制):第一个为accept方法的多态辨析;第二个为visit方法的多态辨析。
设计模式其实是一种堵漏洞的方式,但是没有一种设计模式能够堵完所有的漏洞,即使是组合各种设计模式也是一样。每个设计模式都有漏洞,都有它们解决不了的情况或者变化。每一种设计模式都假定了某种变化,也假定了某种不变化。Visitor模式假定的就是操作变化,而Element类层次结构稳定。

(1)、访问者模式的主要优点有:

1】、访问者模式使得添加新的操作变得容易。如果一些操作依赖于一个复杂的结构对象的话,那么一般而言,添加新的操作会变得很复杂。而使用访问者模式,增加新的操作就意味着添加一个新的访问者类。因此,使得添加新的操作变得容易。
2】、访问者模式使得有关的行为操作集中到一个访问者对象中,而不是分散到一个个的元素类中。这点类似与”中介者模式”。
3】、访问者模式可以访问属于不同的等级结构的成员对象,而迭代只能访问属于同一个等级结构的成员对象。

(2)、访问者模式的主要缺点有:

增加新的元素类变得困难。每增加一个新的元素意味着要在抽象访问者角色中增加一个新的抽象操作,并在每一个具体访问者类中添加相应的具体操作。具体来说,Visitor模式的最大缺点在于扩展类层次结构(增添新的Element子类),会导致Visitor类的改变。因此Visitor模式适用于“Element类层次结构稳定,而其中的操作却经常面临频繁改动”。

(3)、在下面的情况下可以考虑使用访问者模式:

1】、如果系统有比较稳定的数据结构,而又有易于变化的算法时,此时可以考虑使用访问者模式。因为访问者模式使得算法操作的添加比较容易。
2】、如果一组类中,存在着相似的操作,为了避免出现大量重复的代码,可以考虑把重复的操作封装到访问者中。(当然也可以考虑使用抽象类了)
3】、如果一个对象存在着一些与本身对象不相干,或关系比较弱的操作时,为了避免操作污染这个对象,则可以考虑把这些操作封装到访问者对象中。

七、.NET 访问者模式的实现

在现在的Net框架里面,如果要想给现有的类增加新的方法,有了新的方式,那就是“扩展方法”,使用起来和实例方法是一样一样的,而且在Net框架里面,微软自己也写了很多的扩展方法给我们使用。我目前还没有学习到Net的框架类库里面有“访问者模式”实现,看来自己还需努力,革命尚未成功啊。

到此这篇关于.Net行为型设计模式之访问者模式(Visitor)的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • .Net行为型设计模式之命令模式(Command)

    目录 一.动机(Motivate) 二.意图(Intent) 三.结构图(Structure) 四.模式的组成 五.命令模式的代码实现 六.命令模式的实现要点: 1.命令模式的优点: 2.命令模式的缺点: 3.命令模式的使用场景: 七..NET 中命令模式的实现 一.动机(Motivate) 在我们的现实生活中有很多例子可以拿来说明这个模式,我们还拿吃饺子这个事情来说.我的奶奶说了,今天想吃饺子,发出了命令,然后我奶奶就去看电视去了.我们夫妻俩收到命令就开始和面,做饺子馅,包饺子.饺子包好了,我

  • .Net行为型设计模式之迭代器模式(Iterator)

    目录 一.动机(Motivate) 二.意图(Intent) 三.结构图 四.模式的组成 五.迭代器模式的代码实现 六.迭代器模式的实现要点: 迭代器模式的优点: 迭代器模式的缺点: 迭代器模式的使用场景: 七..NET 中迭代器模式的实现 一.动机(Motivate) 在软件构建过程中,集合对象内部结构常常变化各异.但对于这些集合对象,我们希望在不暴露其内部结构的同时,可以让外部客户代码透明地访问其中包含的元素:同时这种“透明遍历”也为“同一种算法在多种集合对象上进行操作”提供了可能.使用面向

  • .Net行为型设计模式之职责链模式(Chain of Responsibility)

    目录 一.动机(Motivate) 二.意图(Intent) 三.结构图(Structure) 四.模式的组成 五.职责链模式的代码实现 六.职责链模式的实现要点: 1.职责链模式的主要优点有: 2.职责链模式的主要缺点有: 3.在下面的情况下可以考虑使用职责链模式: 七..NET 职责链模式的实现 一.动机(Motivate) 在软件构建过程中,一个请求可能被多个对象处理,但是每个请求在运行时只能有一个接受者,如果显示指定,将必不可少地带来请求发送者与接受者的紧耦合.如何使请求的发送者不需要指

  • .Net行为型设计模式之策略模式(Stragety)

    目录 一.动机(Motivate) 二.意图(Intent) 三.结构图(Structure) 四.模式的组成 五.策略模式的代码实现 六.策略模式的实现要点: 1.策略模式的主要优点有: 2.策略模式的主要缺点有: 3.在下面的情况下可以考虑使用策略模式: 七..NET 策略模式的实现 一.动机(Motivate) 在软件构建过程中,某些对象使用的算法可能多种多样,经常改变,如果将这些算法都编码到对象中,将会使对象变得异常复杂:而且有时候支持不使用的算法也是一个性能负担.如何在运行时根据需要透

  • .Net行为型设计模式之中介者模式(Mediator)

    目录 一.动机(Motivate) 二.意图(Intent) 三.结构图(Structure) 四.模式的组成 五.中介者模式的代码实现 六.中介者模式的实现要点: 1.中介者模式的优点 2.中介者模式的缺点 七..NET 中介者模式的实现 一.动机(Motivate) 为什么要使用中介者模式呢?如果不使用中介者模式的话,各个同事对象将会相互进行引用,如果每个对象都与多个对象进行交互时,将会形成如下图所示的网状结构. 从上图可以发现,如果不使用中介者模式的话,每个对象之间过度耦合,这样的既不利于

  • .Net行为型设计模式之状态模式(State)

    目录 一.动机(Motivate) 二.意图(Intent) 三.结构图(Structure) 四.模式的组成 五.状态模式的代码实现 六.状态模式的实现要点: 1.状态模式的优点 2.状态模式的缺点 3.在以下情况下可以使用状态模式: 七..NET 状态模式的实现 一.动机(Motivate) 在软件构建过程中,某些对象的状态如果改变,其行为也会随之而发生变化,比如文档处于只读状态,其支持的行为和读写状态支持的行为就可能完全不同.如何在运行时根据对象的状态来透明地更改对象的行为?而不会为对象操

  • .Net行为型设计模式之模板方法模式(Template Method)

    一.动机(Motivate) “模板方法”,就是有一个方法包含了一个模板,这个模板是一个算法.在我们的现实生活中有很多例子可以拿来说明这个模式,就拿吃饺子这个事情来说,要想吃到饺子必须经过三步,第一步是“和面”,第二步是“包馅”,第三步是“煮饺子”,这三步就是一个算法,我们要想吃到不同的面和馅的饺子,对这三步中的任意一步就行操作就可以,也可以完全定义这三步 在软件构建过程中,对于某一项任务,它常常有稳定的整体操作结构,但各个子步骤却有很多改变的需求,或者由于固有的原因(比如框架与应用之间的关系)

  • .Net行为型设计模式之观察者模式(Observer)

    目录 一.动机(Motivate) 二.意图(Intent) 三.结构图 四.模式的组成 五.观察者模式的代码实现 六.观察者模式的实现要点: 1.观察者模式的优点: 2.观察者模式的缺点: 七..NET 中观察者模式的实现 一.动机(Motivate) “观察者模式”在现实生活中,实例其实是很多的,比如:八九十年代我们订阅的报纸,我们会定期收到报纸,因为我们订阅了.银行可以给储户发手机短信,也是“观察者模式”很好的使用的例子,因为我们订阅了银行的短信业务,当我们账户余额发生变化就会收到通知等.

  • .Net行为型设计模式之访问者模式(Visitor)

    目录 一.动机(Motivate) 二.意图(Intent) 三.结构图(Structure) 四.模式的组成 五.访问者模式的代码实现 六.访问者模式的实现要点: (1).访问者模式的主要优点有: (2).访问者模式的主要缺点有: (3).在下面的情况下可以考虑使用访问者模式: 七..NET 访问者模式的实现 一.动机(Motivate) 在软件构建过程中,由于需求的改变,某些类层次结构中常常需要增加新的行为(方法),如果直接在基类中做这样的更改,将会给子类带来很繁重的变更负担,甚至破坏原有设

  • JAVA设计模式之访问者模式原理与用法详解

    本文实例讲述了JAVA设计模式之访问者模式.分享给大家供大家参考,具体如下: 访问者模式: 一个作用于某对象结构中各元素的操作,使你可以在不改变各元素类数据结构的前提下增加作用于这些元素的新操作. 结构对象是访问者模式必备条件,且这个结构对象必须存在遍历自身各个对象的方法. 适用于:数据结构相对稳定,把数据结构和作用与其上的其它操作解耦,使得操作相对自由. 优点: 1.符合单一职责原则 2.扩展性良好:元素类可以通过接受不同的访问者来实现对不同操作的扩展. 缺点: 1.如果要增加新元素,则会让操

  • Java设计模式之访问者模式使用场景及代码示例

    Java设计模式访问者模式 模式概念 访问者模式表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作.访问者模式适用于数据结构相对稳定算法又易变化的系统,若系统数据结构对象易于变化,则不适合使用访问者模式.访问者模式的优点是增加操作很容易,因为增加操作意味着增加新的访问者. Visitor应用场景 一定会有的疑问:visitor和iterator的区别: visitor可以访问不同的对象(只需要在Element定义对应的accept),但是Ite

  • Android编程设计模式之访问者模式详解

    本文实例讲述了Android编程设计模式之访问者模式.分享给大家供大家参考,具体如下: 一.介绍 访问者模式是一种将数据操作与数据结构分离的设计模式,它是<设计模式>中23种设计模式中最复杂的一个,但它的使用频率并不高,正如<设计模式>的作者GOF对访问者模式的描述:大多数情况下,你不需要使用访问者模式,但是当你一旦需要使用它时,那你就是真的需要它了. 访问者模式的基本想法是,软件系统中拥有一个由许多对象构成的.比较稳定的对象结构,这些对象的类都拥有一个accept方法用来接受访问

  • JS设计模式之访问者模式定义与用法分析

    本文实例讲述了JS设计模式之访问者模式定义与用法.分享给大家供大家参考,具体如下: 在访问者模式中,主要包括下面几个角色 1.抽象访问者:抽象类或者接口,声明访问者可以访问哪些元素,具体到程序中就是visit方法中的参数定义哪些对象是可以被访问的. 2.访问者:实现抽象访问者所声明的方法,它影响到访问者访问到一个类后该干什么,要做什么事情. 3.抽象元素类:接口或者抽象类,声明接受哪一类访问者访问,程序上是通过accept方法中的参数来定义的.抽象元素一般有两类方法,一部分是本身的业务逻辑,另外

  • .Net行为型设计模式之解释器模式(Interpreter)

    目录 一.动机(Motivate) 二.意图(Intent) 三.结构图(Structure) 四.模式的组成 五.解释器模式的代码实现 六.解释器模式的实现要点: 1.解释器模式的主要优点有: 2.解释器模式的主要缺点有: 3.在下面的情况下可以考虑使用解释器模式: 七..NET 解释器模式的实现 八.总结 一.动机(Motivate) 在软件构建过程中,如果某一特定领域的问题比较复杂,类似的模式不断重复出现,如果使用普通的编程方式来实现将面临非常频繁的变化.在这种情况下,将特定领域的问题表达

  • Java 深入理解创建型设计模式之原型模式

    1.思考问题 现在有一只羊 tom,姓名为: tom,年龄为:1,颜色为:白色,请编写程序创建和 tom羊属性完全相同的10只羊. 按照传统的思路来,我们可能会按照下面的方式去写. 那么这种写法的优缺点自然而然就出来了: 优点是比较好理解,简单易操作. 缺点是在创建新的对象时,总是需要重新获取原始对象的属性,如果创建的对象比较复杂时,效率较低.总是需要重新初始化对象,而不是动态地获得对象运行时的状态,不够灵活. 改进的思路分析:Java中Object类是所有类的根类,Object类提供了一个 c

  • Java 深入理解创建型设计模式之建造者模式

    1.提出问题 假如说,我们需要建房子:这一过程为打桩.砌墙.封顶.房子有各种各样的,比如普通房,高楼,别墅,各种房子的过程虽然一样,但是要求不要相同的.3)请编写程序,完成需求. 传统的想法应该就是下面这个类图的形式.. 那么这种写法的优点就是 比较好理解,简单易操作. 缺点则是:设计的程序结构,过于简单,没有设计缓存层对象,程序的扩展和维护不好.也就是说,这种设计方案,把产品(即: 房子)和创建产品的过程(即: 建房子流程)封装在一起,耦合性增强了. 解决方案:  将产品和产品建造过程解耦 

  • java编程创建型设计模式工厂方法模式示例详解

    目录 1.什么是工厂方法模式? 2.案例实现 3.JDK中的工厂方法模式 1.什么是工厂方法模式? 工厂方法模式设计方案:  将披萨项目的实例化功能抽象成抽象方法,在不同的口味点餐子类中具体实现. 工厂方法模式:  定义了一个创建对象的抽象方法,由子类决定要实例化的类.工厂方法模式将对象的实例化推迟到子类. 何时使用?  不同条件下创建不用实例时.方法是让子类实现工厂接口. 2.案例实现 假如说,我们现在有这样一个需求:客户在点披萨时,可以点不同口味的披萨,比如北京的奶酪pizza.北京的胡椒p

随机推荐