Head First设计模式之访问者模式

一、定义

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

访问者模式适用于数据结构相对稳定的系统, 它把数据结构和作用于数据结构之上的操作之间的耦合度降低,使得操作集合可以相对自由地改变。

数据结构的每一个节点都可以接受一个访问者的调用,此节点向访问者对象传入节点对象,而访问者对象则反过来执行节点对象的操作。这样的过程叫做“双重分派”。节点调用访问者,将它自己传入,访问者则将某算法针对此节点执行。

二、结构图

  这里需要明确一点:访问者模式中具体访问者的数目和具体节点的数目没有任何关系。从访问者的结构图可以看出,访问者模式涉及以下几类角色。

  • 抽象访问者角色(Vistor):声明一个活多个访问操作,使得所有具体访问者必须实现的接口。
  • 具体访问者角色(ConcreteVistor):实现抽象访问者角色中所有声明的接口。
  • 抽象节点角色(Element):声明一个接受操作,接受一个访问者对象作为参数。
  • 具体节点角色(ConcreteElement):实现抽象元素所规定的接受操作。
  • 结构对象角色(ObjectStructure):节点的容器,可以包含多个不同类或接口的容器。

三、适用场景

1、对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作。

2、需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,也不希望在增加新操作时修改这些类。

四、优缺点

优点: 1、符合单一职责原则。 2、优秀的扩展性。 3、灵活性。

缺点: 1、具体元素对访问者公布细节,违反了迪米特原则。 2、具体元素变更比较困难。 3、违反了依赖倒置原则,依赖了具体类,没有依赖抽象。

五、实现

思路:商家定义了一个套餐A,为套餐A添加了土豆和花生,然后张三、李四才点了套餐A。

好处:不管多少人来,都是给他们的菜都是一样的

坏处:如果套餐A 突然加了一个菜 海带, 导致所有人都要来拿海带,所以变化是非常困难的。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DesignPatterns.Visitor
{
    class Program
    {
        static void Main(string[] args)
        {
            Food a = new Potato();
            Food b = new Peanut();

            var combo = new Combo();
            combo.Add(a);
            combo.Add(b);

            Visitor charger = new Charger("张三");
            Visitor workerOfPharmacy = new WorkerOfPharmacy("李四"); 

            combo.Accpet(charger);
            Console.WriteLine();
            combo.Accpet(workerOfPharmacy);
        }
    }

    /// <summary>
    /// 抽象访问者
    /// </summary>
    public abstract class Visitor
    {
        protected string name { get; set; }

        public Visitor(string name)
        {
            this.name = name;
        }

        public abstract void visitor(Potato a);

        public abstract void visitor(Peanut b);
    }
    /// <summary>
    /// 具体访问者:张三
    /// </summary>
    public class Charger : Visitor
    {
        public Charger(string name) : base(name) { }

        public override void visitor(Potato a)
        {
            Console.WriteLine("张三:" + this.name + " 取菜 " + a.GetName());
        }

        public override void visitor(Peanut b)
        {
            Console.WriteLine("张三:" + this.name + " 取菜 " + b.GetName());
        }
    }

    /// <summary>
    /// 具体访问者:李四
    /// </summary>
    public class WorkerOfPharmacy : Visitor
    {
        public WorkerOfPharmacy(string name) : base(name) { }
        public override void visitor(Potato a)
        {
            Console.WriteLine("李四:" + this.name + " 取菜 " + a.GetName() );
        }

        public override void visitor(Peanut b)
        {
            Console.WriteLine("李四:" + this.name + " 取菜 " + b.GetName());
        }
    }

    /// <summary>
    /// 抽象元素:食物
    /// </summary>
    public abstract class Food
    {
        protected string name { get; set; } 

        public Food()
        {
            name = "我是食物";
        }

        public string GetName()
        {
            return name;
        }

        public abstract void Accept(Visitor visitor);
    }

    /// <summary>
    /// 具体元素:土豆
    /// </summary>
    public class Potato : Food
    {
        public Potato()
        {
            this.name = "土豆";
        }

        public override void Accept(Visitor visitor)
        {
            visitor.visitor(this);
        }
    }
    /// <summary>
    /// 具体元素:花生
    /// </summary>
    public class Peanut : Food
    {
        public Peanut()
        {
            this.name = "花生";
        }

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

    /// <summary>
    /// 具体元素:套餐
    /// </summary>
    public class Combo
    {
        private List<Food> list = new List<Food>();
        public void Accpet(Visitor visitor)
        {
            foreach (var item in list)
            {
                item.Accept(visitor);
            }
        }

        public void Add(Food med)
        {
            list.Add(med);
        }

        public void Remove(Food med)
        {
            list.Remove(med);
        }
    }
}

参考

http://blog.csdn.net/heyangyi_19940703/article/details/51374416

http://www.cnblogs.com/zhili/p/VistorPattern.html

http://www.cnblogs.com/JsonShare/p/7380772.html

欢迎阅读本系列文章:Head First设计模式之目录

时间: 2024-10-10 16:44:17

Head First设计模式之访问者模式的相关文章

PHP教程:掌握php设计模式之访问者模式

PHP教程:掌握php设计模式之访问者模式 这篇文章主要帮助大家轻松掌握php设计模式之访问者模式,感兴趣的小伙伴们可以参考一下 访问者模式解决的问题 在我们的代码编写过程当中,经常需要对一些类似的对象添加一些的代码,我们以一个计算机对象打印组成部分为例来看下: /** * 抽象基类 */ abstract class Unit { /** *获取名称 */ abstract public function getName(); } /** * Cpu类 */ class Cpu extends

设计模式之访问者模式(Visitor)摘录

23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而一个对象创建型模式将实例化委托给另一个对象.创建型模式有两个不断出现的主旋律.第一,它们都将关于该系统使用哪些具体的类的信息封装起来.第二,它们隐藏了这些类的实例是如何被创建和放在一起的.整个系统关于这些对象所知道的是由抽象类所定义的接口.因此,创建型模式在什么被创建,谁创建它,它是怎样被创建的,以

【设计模式】——访问者模式

访问者模式(Visitor),表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作. 访问者模式结构图 访问者模式使用与数据结构相对比较稳定的系统,即数据结构和作用与结构上的操作之间的耦合解脱开,使得操作集合可以相对自由的演化.其目的,要把处理从数据结构分离开来.很多系统可以按照算法和数据结构分开,如果这样的系统有比较稳定的数据结构,又有易于变化的算法的话,使用访问者模式就是比较合适的,因为访问者模式使得算法操作的增加变得容易.反之,如果这样的

【设计模式】访问者模式

在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法.通过这种方式,元素的执行算法可以随着访问者改变而改变.这种类型的设计模式属于行为型模式.根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作. 介绍 意图:主要将数据结构与数据操作分离. 主要解决:稳定的数据结构和易变的操作耦合问题. 何时使用:需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,使用访问者模式将这些

JAVA设计模式之 访问者模式【Visitor Pattern】

一.概述 访问者模式是一种较为复杂的行为型设计模式,它包含访问者和被访问元素两个主要组成部分,这些被访问的元素通常具有不同的类型,且不同的访问者可以对它们进行不同的访问操作.在使用访问者模式时,被访问元素通常不是单独存在的,它们存储在一个集合中,这个集合被称为"对象结构",访问者通过遍历对象结构实现对其中存储的元素的逐个操作.访问者模式是一种对象行为型模式. 二.适用场景 当有多种类型的访问者(或是操作者) 对一组被访问者对象集合(或是对象结构)进行操作(其中对象集合也包含多种类型对象

22.设计模式_访问者模式

一.引言 在上一篇博文中分享了责任链模式,责任链模式主要应用在系统中的某些功能需要多个对象参与才能完成的场景.在这篇博文中,我将为大家分享我对访问者模式的理解. 二.访问者模式介绍 2.1 访问者模式的定义 访问者模式是封装一些施加于某种数据结构之上的操作.一旦这些操作需要修改的话,接受这个操作的数据结构则可以保存不变.访问者模式适用于数据结构相对稳定的系统, 它把数据结构和作用于数据结构之上的操作之间的耦合度降低,使得操作集合可以相对自由地改变. 数据结构的每一个节点都可以接受一个访问者的调用

JS常用的设计模式(8)——访问者模式

GOF官方定义: 访问者模式是表示一个作用于某个对象结构中的各元素的操作.它使可以在不改变各元素的类的前提下定义作用于这些元素的新操作.我们在使用一些操作对不同的 对象进行处理时,往往会根据不同的对象选择不同的处理方法和过程.在实际的代码过程中,我们可以发现,如果让所有的操作分散到各个对象中,整个系统会变得 难以维护和修改.且增加新的操作通常都要重新编译所有的类.因此,为了解决这个问题,我们可以将每一个类中的相关操作提取出来,包装成一个独立的对象,这 个对象我们就称为访问者(Visitor).利

Java设计模式之访问者模式

本文继续23种设计模式系列之访问者模式. 定义 封装某些作用于某种数据结构中各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作. class A { public void method1(){ System.out.println("我是A"); } public void method2(B b){ b.showA(this); } } class B { public void showA(A a){ a.method1(); } } 看一下在类A中,方法m

设计模式(17) 访问者模式(VISITOR) C++实现

意图: 表示一个作用于某对象结构的各元素的操作.它使你可以再不改变各元素的类的前提下定义作用于这些元素的新操作. 动机: 之前在学校的最后一个小项目就是做一个编译器,当时使用的就是访问者模式. 在静态分析阶段,将源程序表示为一个抽象语法树,编译器需要在抽象语法树的基础上实施某些操作以进行静态语义分析.可能需要定义许多操作以进行类型检查.代码优化.流程分析.检查变量是否在使用前被赋值,等等. 这个需求的特点是:要求对不同的节点进行不同的处理. 常规设计方法:不同的节点封装不同的操作. 缺点是,节点