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-09-16 16:00:14

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

设计模式之访问者模式

        刚刚学完设计模式的访问者模式(编译器模式),这里就对该模式进行了总结与分析. 一.产生原因         这里存在一个这样的问题:如果某系统已经完成了一个类层次并提供了满足需求的所有接口,现在要增加新的需求,我们需要怎么做?         可能你会采用增加该需求并把整个层次结构统统修改一遍.然而如果需求变动会不停的发生,而且需求的任何变动都会让整个结构统统修改一遍,此时你会怎么做呢?        所以,我们现在需要对这个系统结构进行重构,访问者模式也许就是你解决上面问题最好

乐在其中设计模式(C#) - 访问者模式(Visitor Pattern)

原文:乐在其中设计模式(C#) - 访问者模式(Visitor Pattern)[索引页][源码下载] 乐在其中设计模式(C#) - 访问者模式(Visitor Pattern) 作者:webabcd 介绍 表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作. 示例 有一个Message实体类,某些对象对它的操作有Insert()和Get()方法,现在要针对其中某一方法进行操作. MessageModel using System;using

C++设计模式之访问者模式_C 语言

前言 这是23+1(简单工厂模式)之中的最后一个了--访问者模式.访问者模式也是一个比较麻烦的设计模式.我也没有实战经验,对于访问者模式的理解完全来自GOF的<设计模式:可复用面向对象软件的基础>,而这篇文章就是根据对这本书的理解而写出来的.在读<设计模式:可复用面向对象软件的基础>的时候,让我想起自己做过的一个项目,该项目虽然没有使用访问者模式,但是,今天理解了该模式,如果使用该模式对之前做过的项目进行重构,将是一个不错的想法. 访问者模式 在GOF的<设计模式:可复用面向

JAVA设计模式之访问者模式详解_java

在阎宏博士的<JAVA与模式>一书中开头是这样描述访问者(Visitor)模式的: 访问者模式是对象的行为模式.访问者模式的目的是封装一些施加于某种数据结构元素之上的操作.一旦这些操作需要修改的话,接受这个操作的数据结构则可以保持不变. 分派的概念 变量被声明时的类型叫做变量的静态类型(Static Type),有些人又把静态类型叫做明显类型(Apparent Type):而变量所引用的对象的真实类型又叫做变量的实际类型(Actual Type).比如: 复制代码 代码如下: List lis

设计模式:访问者模式(Vistor)

访问者模式表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作. 访问者模式的目的是封装一些施加于某种数据结构元素之上的操作,一旦这些操作需要修改的话,接受这个操作的数据结构可以保持不变.为不同类型的元素提供多种访问操作方式,且可以在不修改原有系统的情况下增加新的操作方式,这就是访问者模式的模式动机. 访问者模式即表示一个作用于某对象结构中的各元素的操作,它使我们可以在不改变各元素的类的前提下定义作用于这些元素的新操作. 访问者模式适用于数据结构

php设计模式 Visitor 访问者模式

复制代码 代码如下:<?php /** * 访问者模式 * * 表示一个作用于某对象结构中的各元素的操作,可以在不改变各元素的类的前提下定义作用于这些元素的新操作 * */ abstract class Visitor { abstract public function visitCroncreteElementA($element); abstract public function visitCroncreteElementB($element); } class ConcreteVisi

php设计模式 Visitor 访问者模式_php技巧

复制代码 代码如下: <?php /** * 访问者模式 * * 表示一个作用于某对象结构中的各元素的操作,可以在不改变各元素的类的前提下定义作用于这些元素的新操作 * */ abstract class Visitor { abstract public function visitCroncreteElementA($element); abstract public function visitCroncreteElementB($element); } class ConcreteVis

轻松掌握python设计模式之访问者模式_python

本文实例为大家分享了python访问者模式代码,供大家参考,具体内容如下 """访问者模式""" class Node(object): pass class A(Node): pass class B(Node): pass class C(A, B): pass class Visitor(object): def visit(self, node, *args, **kwargs): meth = None ""&quo

设计模式——21访问者模式(Visitor)

21.访问者模式(Visitor)访问者模式把数据结构和作用于结构上的操作解耦合,使得操作集合可相对自由地演化.访问者模式适用于数据结构相对稳定算法又易变化的系统.因为访问者模式使得算法操作增加变得容易.若系统数据结构对象易于变化,经常有新的数据对象增加进来,则不适合使用访问者模式.访问者模式的优点是增加操作很容易,因为增加操作意味着增加新的访问者.访问者模式将有关行为集中到一个访问者对象中,其改变不影响系统数据结构.其缺点就是增加新的数据结构很困难.-- From 百科简单来说,访问者模式就是