首页 > 其他分享 >访问者模式

访问者模式

时间:2024-02-29 15:26:05浏览次数:23  
标签:void 模式 new 操作 数据结构 public 访问者

简介

访问者模式(Visitor Pattern)是一种行为型设计模式,用于在不改变被访问元素的类的前提下,定义对这些元素的新操作。该模式通过将算法与数据结构分离,使得可以在不修改数据结构的情况下,增加新的操作。

结构

  1. 访问者(Visitor):定义了对于每个元素类所要执行的操作。这些操作可以是不同的,甚至是完全不同的,而且可以通过访问者模式来轻松地增加新的操作。

  2. 具体访问者(Concrete Visitor):实现了访问者接口定义的操作,对应于每一种具体的访问者。

  3. 元素(Element):定义了一个接受访问者的方法,通常是 accept(Visitor visitor),使得访问者可以访问它。

  4. 具体元素(Concrete Element):实现了接受访问者的方法,是被访问的对象,它定义了访问者具体访问的行为。

  5. 对象结构(Object Structure):可以包含多种不同类型的元素,提供了一个高层接口,让访问者可以访问它所包含的所有元素。

案例

 假设有一个图形库,其中包含不同类型的图形对象:圆形(Circle)和矩形(Rectangle)。我们希望能够实现对这些图形对象执行不同的操作,比如计算它们的面积

using System;
using System.Collections.Generic;

// 图形对象接口
interface IShape
{
    void Accept(IVisitor visitor);
}

// 圆形类
class Circle : IShape
{
    public double Radius { get; }

    public Circle(double radius)
    {
        Radius = radius;
    }

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

// 矩形类
class Rectangle : IShape
{
    public double Width { get; }
    public double Height { get; }

    public Rectangle(double width, double height)
    {
        Width = width;
        Height = height;
    }

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

// 访问者接口
interface IVisitor
{
    void Visit(Circle circle);
    void Visit(Rectangle rectangle);
}

// 计算面积的访问者
class AreaVisitor : IVisitor
{
    public double TotalArea { get; private set; }

    public void Visit(Circle circle)
    {
        TotalArea += Math.PI * Math.Pow(circle.Radius, 2);
    }

    public void Visit(Rectangle rectangle)
    {
        TotalArea += rectangle.Width * rectangle.Height;
    }
}

class Program
{
    static void Main(string[] args)
    {
        var shapes = new List<IShape>
        {
            new Circle(5),
            new Rectangle(3, 4),
            new Circle(2)
        };

        // 计算总面积
        var areaVisitor = new AreaVisitor();
        foreach (var shape in shapes)
        {
            shape.Accept(areaVisitor);
        }
        Console.WriteLine($"Total area: {areaVisitor.TotalArea}");
    }
}

如果增加了一个业务,需要绘制图形,那么只需加一个绘制图形的访问者

// 绘制访问者
class DrawVisitor : IVisitor
{
    public void Visit(Circle circle)
    {
        Console.WriteLine($"Drawing circle with radius {circle.Radius}");
    }

    public void Visit(Rectangle rectangle)
    {
        Console.WriteLine($"Drawing rectangle with width {rectangle.Width} and height {rectangle.Height}");
    }
}
class Program
{
    static void Main(string[] args)
    {
        var shapes = new List<IShape>
        {
            new Circle(5),
            new Rectangle(3, 4),
            new Circle(2)
        };

        // 计算总面积
        var areaVisitor = new AreaVisitor();
        foreach (var shape in shapes)
        {
            shape.Accept(areaVisitor);
        }
        Console.WriteLine($"Total area: {areaVisitor.TotalArea}");

        // 绘制图形
        var drawVisitor = new DrawVisitor();
        foreach (var shape in shapes)
        {
            shape.Accept(drawVisitor);
        }
    }
}

优点

  1. 分离关注点:访问者模式将数据结构与数据操作分离开来,使得可以在不改变数据结构的前提下定义新的操作。

  2. 开闭原则:符合开闭原则,允许向现有系统添加新的操作,而无需修改现有的代码。

  3. 易扩展性:可以通过添加新的具体访问者来轻松地扩展系统,而不会影响到原有的数据结构。

  4. 易维护性:由于各个操作被封装在具体访问者中,因此修改或扩展操作时不会影响其他部分的代码,提高了代码的可维护性。

缺点

  1. 增加新元素困难:如果需要添加新的元素类型,除了要修改元素接口,还需要修改所有的访问者类,这增加了系统的复杂性。

  2. 破坏封装性:访问者模式会将数据结构的内部细节暴露给具体访问者,使得数据结构的封装性降低。

  3. 不易理解:访问者模式的结构相对复杂,需要理解和掌握访问者、具体访问者、元素等多个角色,因此对于初学者来说不太容易理解。

  4. 适用范围有限:访问者模式通常适用于数据结构相对稳定,但经常需要在此数据结构上定义新操作的情况。如果数据结构频繁变化,访问者模式可能不太适用。

适用场景

  1. 操作与数据结构分离:当系统中的数据结构相对稳定,但经常需要定义新的操作或功能时,访问者模式可以将操作与数据结构分离,使得可以在不改变数据结构的情况下定义新的操作。

  2. 多个不相关的操作:当需要对一个数据结构进行多个不相关的操作,并且这些操作需要根据数据结构中的具体元素类型来执行不同的行为时,访问者模式能够为每个操作定义一个具体访问者,并在数据结构中分发这些访问者,以执行相应的操作。

  3. 数据结构稳定,但操作频繁变化:当数据结构相对稳定,但操作频繁变化时,可以使用访问者模式来封装变化的部分,使得可以轻松地扩展系统,而不会影响到现有的数据结构。

  4. 操作涉及多个不同的类:当需要对一个数据结构中的元素进行多种不同的操作,并且这些操作涉及到多个不同的类时,访问者模式可以将这些操作封装在不同的具体访问者中,使得每个具体访问者只关注自己的操作逻辑,提高了系统的可维护性和可扩展性。

标签:void,模式,new,操作,数据结构,public,访问者
From: https://www.cnblogs.com/mchao/p/18044270

相关文章

  • 桥接模式(bridge pattern)
    定义:将抽象部分与它的实现部分分离,使他们都可以独立地变化桥接模式使用一种巧妙的方式处理多层继承存在的问题,用抽象关联来取代传统的多层继承,将类之间的静态继承关系转变为动态的组合关系,使得系统更加灵活,并易于扩展,有效的控制了系统中的类的个数(避免了继承层次的指数级爆炸),将两......
  • 中介者模式
    简介中介者模式(MediatorPattern)是一种行为型设计模式,旨在减少对象之间的直接通信,通过引入一个中介对象来促进对象之间的松耦合通信。在这种模式中,对象之间不再直接相互引用,而是通过中介者对象来进行通信。中介者模式通常包含以下几个角色:中介者(Mediator):负责定义接口,用于与各......
  • 实战上,通过一段ID 生成器代码,学习如何发现,代码质量的问题(设计模式)
    ID生成器的需求背景介绍ID中文翻译为标识Identifier,这个概念在生活,工作中随处可见,比如身份证、商业条形码、二维码、车牌号、驾照号。聚焦到软件开发中,ID常用来标识一些业务信息的唯一标识,比如订单的单号或者数据库中的唯一主键,比如地址中ID字段(实际上时没有业务含义的,对用......
  • 迭代器模式
    简介迭代器模式是一种行为型设计模式,它用于提供一种顺序访问聚合对象(如列表、集合、数组等)中的元素,而不需要暴露该对象的内部表示。这种模式将迭代操作从聚合对象中分离出来,使得可以在不同的聚合对象上使用相同的迭代逻辑。在迭代器模式中,通常会有两个主要角色:迭代器(Iterator......
  • 解释器模式
    简介解释器模式(InterpreterPattern)是一种行为设计模式,用于定义一种语言的语法,并提供一个解释器来解释该语言中的表达式。这种模式通常用于处理特定类型的问题,例如解释一种特定的语言或表示法。结构解释器模式通常包含以下角色:抽象表达式(AbstractExpression):定义了一个抽象......
  • 命令模式
    简介命令模式是一种行为设计模式,它允许将请求或操作封装为单独的对象。这些请求可以被参数化,队列化,记录日志,以及支持撤销操作。以下是命令模式的几个关键角色:命令(Command):抽象命令接口,定义了执行命令的方法,通常包含一个execute()方法。具体命令(ConcreteCommand):实现......
  • 职责链模式
    简介职责链模式(ChainofResponsibilityPattern)是一种行为设计模式,它允许你将请求沿着处理者链进行传递,直到有一个处理者能够处理它为止。这种模式允许多个对象都有机会处理请求,避免了发送者和接收者之间的耦合关系。结构Handler(处理者):定义处理请求的接口,并维护一个后继处理......
  • 观察者模式
    importtimeclassObserver:def__init__(self,name)->None:self.name=namedefupdate(self,message):print("name%sreceivedmessage:%s"%(self.name,message))classSubject:def__init__(self)->No......
  • 策略模式
    importtimeclassLocalStrategy:defexecute(self):print("thisisalocal104execute")classSaasStrategy:defexecute(self):print("thisisasaasexecute")classSwitch:def__init__(self,strategy......
  • 23种设计模式 - 单例模式
      饿汉式特点:线程安全,调用效率高,但是不能延时加载publicclassSingletonDemo01{privatestaticSingletonDemo1instance=newSingletonDemo1();privateSingletonDemo1(){}publicstaticSingletonDemo1getInstance(){returninstance;}......