设计模式(二十三)访问者

这篇具有很好参考价值的文章主要介绍了设计模式(二十三)访问者。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、定义

表示一个作用于某对象结构中的各个元素的操作。访问者模式让你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。访问者模式是一种对象行为型模式

二、描述

访问者模式是一种较为复杂的行为型模式,它包含访问者和被访问元素两个主要组成部分,这些被访问的元素通常具有不同的类型,且不同的访问者可以对它们进行不同的访问操作。例如:处方单中的各种药品信息就是被访问的元素,而划价人员和药房工作人员就是访问者。访问者模式可以使得用户在不修改现有系统的情况下扩展系统的功能,为这些不同类型的元素增加新的操作,包含以下五个角色:设计模式(二十三)访问者1、Visitor(抽象访问者):抽象访问者为对象结构中每一个具体元素类ConcreteElement声明一个访问操作,从这个操作的名称或参数类型可以清楚知道需要访问的具体元素的类型,具体访问者则需要实现这些操作方法,定义对这些元素的访问操作。
2、ConcreteVisitor(具体访问者)具体访问者实现了抽象访问者声明的方法,每一个操作作用于访问对象结构中一种类型的元素。
3、Element(抽象元素)一般是一个抽象类或接口,定义一个Accept方法,该方法通常以一个抽象访问者作为参数。
4、ConcreteElement(具体元素)具体元素实现了Accept方法,在Accept方法中调用访问者的访问方法以便完成一个元素的操作。
5、ObjectStructure(对象结构):对象结构是一个元素的集合,用于存放元素对象,且提供便利其内部元素的方法。

三、例子

X公司开发部想要为某企业开发一个OA系统,员工管理模块分为正式员工和临时工,HR部门和财务部门每周按各自计算公式分别汇总员工对应工时、工资
设计模式(二十三)访问者IEmployee:员工接口,充当抽象元素

public interface IEmployee
{
    void Accept(Department handler);
}

FullTimeEmployee,PartTimeEmployee:正式员工类、临时员工类,充当具体元素

public class FullTimeEmployee : IEmployee
{
    public string Name { get; set; }
    public double WeeklyWage { get; set; }
    public int WorkTime { get; set; }

    public FullTimeEmployee(string name, double weeklyWage, int workTime)
    {
        this.Name = name;
        this.WeeklyWage = weeklyWage;
        this.WorkTime = workTime;
    }

    public void Accept(Department handler)
    {
        handler.Visit(this);
    }
}

public class PartTimeEmployee : IEmployee
{
    public string Name { get; set; }
    public double HourWage { get; set; }
    public int WorkTime { get; set; }

    public PartTimeEmployee(string name, double hourWage, int workTime)
    {
        this.Name = name;
        this.HourWage = hourWage;
        this.WorkTime = workTime;
    }

    public void Accept(Department handler)
    {
        handler.Visit(this);
    }
}

EmployeeList:员工集合类,充当对象结构

public class EmployeeList
{
    private IList<IEmployee> empList = new List<IEmployee>();

    public void AddEmployee(IEmployee emp)
    {
        this.empList.Add(emp);
    }

    public void Accept(Department handler)
    {
        foreach (var emp in empList)
        {
            emp.Accept(handler);
        }
    }
}

Department:部门抽象类,充当抽象访问者

public abstract class Department
{
    // 声明一组重载的访问方法,用于访问不同类型的具体元素
    public abstract void Visit(FullTimeEmployee employee);
    public abstract void Visit(PartTimeEmployee employee);
}

FinanceDepartment,HRDepartment:财务部门类、人力部门类,充当具体访问者

public class FinanceDepartment : Department
{
    // 实现财务部对兼职员工数据的访问
    public override void Visit(PartTimeEmployee employee)
    {
        int workTime = employee.WorkTime;
        double hourWage = employee.HourWage;
        Console.WriteLine("临时工 {0} 实际工资为:{1} 元", employee.Name, workTime * hourWage);
    }

    // 实现财务部对全职员工数据的访问
    public override void Visit(FullTimeEmployee employee)
    {
        int workTime = employee.WorkTime;
        double weekWage = employee.WeeklyWage;

        if (workTime > 40)
        {
            weekWage = weekWage + (workTime - 40) * 50;
        }
        else if (workTime < 40)
        {
            weekWage = weekWage - (40 - workTime) * 80;
            if (weekWage < 0)
            {
                weekWage = 0;
            }
        }

        Console.WriteLine("正式员工 {0} 实际工资为:{1} 元", employee.Name,  weekWage);
    }
}

public class HRDepartment : Department
{
    // 实现人力资源部对兼职员工数据的访问
    public override void Visit(PartTimeEmployee employee)
    {
        int workTime = employee.WorkTime;
        Console.WriteLine("临时工 {0} 实际工作时间为:{1} 小时", employee.Name, workTime);
    }

    // 实现人力资源部对全职员工数据的访问
    public override void Visit(FullTimeEmployee employee)
    {
        int workTime = employee.WorkTime;
        Console.WriteLine("正式员工 {0} 实际工作时间为:{1} 小时", employee.Name, workTime);

        if (workTime > 40)
        {
            Console.WriteLine("正式员工 {0} 加班时间为:{1} 小时", employee.Name, workTime - 40);
        }
        else if (workTime < 40)
        {
            Console.WriteLine("正式员工 {0} 请假时间为:{1} 小时", employee.Name, 40 - workTime);
        }
    }
}

Program:测试代码

EmployeeList empList = new EmployeeList();
IEmployee fteA = new FullTimeEmployee("梁思成", 3200.00, 45);
IEmployee fteB = new FullTimeEmployee("徐志摩", 2000, 40);
IEmployee fteC = new FullTimeEmployee("梁徽因", 2400, 38);
IEmployee fteD = new PartTimeEmployee("方鸿渐", 80, 20);
IEmployee fteE = new PartTimeEmployee("唐宛如", 60, 18);

empList.AddEmployee(fteA);
empList.AddEmployee(fteB);
empList.AddEmployee(fteC);
empList.AddEmployee(fteD);
empList.AddEmployee(fteE);

Department dept = new HRDepartment();
if (dept != null)
{
    empList.Accept(dept);
}
Console.ReadLine();

设计模式(二十三)访问者在系统中新增访问者,那么无需修改源代码,只需新增一个新的具体访问者类即可,符合开闭原则,但是,如果要新增具体元素,比如新增一个新的员工类型为“退休人员”,由于原系统并未提供相应的访问接口,因此必须对原有系统进行修改。所以,从新增新的元素来看,访问者模式违背了开闭原则。访问者模式与抽象工厂模式类似,对于开闭原则的支持具有“倾斜”性,可以方便地新增访问者,但是添加新的元素较为麻烦。

四、总结

1、优点

(1)访问者模式增加新的访问操作很方便。使用访问者模式,增加新的访问操作就意味着增加一个新的具体访问者类,实现简单,无须修改源代码,符合开闭原则。
(2)访问者模式将有关元素对象的访问行为集中到一个访问者对象中,而不是分散在一个个的元素类中。类的职责更加清晰,有利于对象结构中元素对象的复用,相同的对象结构可以供多个不同的访问者访问。
(3)访问者模式让用户能够在不修改现有元素类层次结构的情况下,定义作用于该层次结构的操作。

2、缺点

(1)增加新的元素类很困难。在访问者模式中,每增加一个新的元素类都意味着要在抽象访问者角色中增加一个新的抽象操作,并在每一个具体访问者类中增加相应的具体操作,这违背了开闭原则的要求。
(2)破坏封装。访问者模式要求访问者对象访问并调用每一个元素对象的操作,这意味着元素对象有时候必须暴露一些自己的内部操作和内部状态,否则无法供访问者访问。文章来源地址https://www.toymoban.com/news/detail-825069.html

到了这里,关于设计模式(二十三)访问者的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 设计模式——访问者模式

    访问者模式(Visitor Pattern)是一种行为型设计模式,它主要用于在不修改现有类结构的前提下向对象结构添加新的操作。访问者模式通过定义一个访问者接口,使得可以在不改变元素类的情况下,为各个元素类增加新的功能。 元素接口(Element Interface): 定义了一个accept()方法

    2024年01月18日
    浏览(43)
  • 设计模式—访问者模式

     需求:店铺采购了一批水果(苹果及橘子),现在市场监督局来店里检查过期的水果。 如果此时再添加一个操作:找出新品上市的水果。 上述代码中,FruitMarket为应付新增操作,增加了相应的方法来满足要求,但这样破坏了FruitMarket的结构。 本质是将数据结构和数据操作分

    2024年02月10日
    浏览(44)
  • 设计模式——19. 访问者模式

    访问者模式(Visitor Pattern)是一种行为型设计模式,它允许你在不改变元素类(被访问者)的前提下,定义对元素的新操作(访问者),并将这些操作封装到独立的访问者类中。这样,你可以在不修改被访问者的类的情况下,通过不同的访问者来执行不同的操作。 访问者模式

    2024年02月07日
    浏览(26)
  • Java设计模式-访问者模式

    在软件开发领域中,设计模式是解决常见问题的经典方法。其中,访问者模式是一种强大且灵活的设计模式,用于处理对象结构中的元素,并根据不同的访问者实现不同的操作。 访问者模式是一种行为型设计模式,它允许你在不改变元素类的前提下定义新的操作。该模式将算

    2024年02月06日
    浏览(44)
  • js设计模式:访问者模式

    将操作方法封装在一个访问者对象中,而不是封装在每个被访问对象当中。 访问者对象可以通过调用被访问者的接口,用来操作被访问者。

    2024年02月22日
    浏览(37)
  • 设计模式之访问者模式(下)

    3)访问者模式与组合模式联用 1.概述 在访问者模式中,包含一个用于存储元素对象集合的对象结构,可以使用迭代器来遍历对象结构,同时具体元素之间可以存在整体与部分关系,有些元素作为容器对象,有些元素作为成员对象,可以使用组合模式来组织元素。 2.结构图

    2024年04月25日
    浏览(30)
  • 设计模式之访问者模式(上)

    访问者模式 1)概述 1.概念 访问者模式包含 访问者 和 被访问元素 两个主要组成部分。 处方单中的各种药品信息就是 被访问的元素 ,而划价人员和药房工作人员就是 访问者 ,被访问的元素通常具有不同的类型,且不同的访问者可以对它们进行不同的访问操作。 被访问元素

    2024年04月25日
    浏览(29)
  • 03-JAVA设计模式-访问者模式

    访问者模式(Visitor Pattern)是软件设计模式中的一种行为模式,它用于将数据结构中的元素与操作这些元素的操作解耦。这种模式使得可以在不修改数据结构的情况下添加新的操作。 在访问者模式中,我们定义了两个主要角色: 访问者(Visitor): 这个接口声明了一个访问元

    2024年04月29日
    浏览(34)
  • 设计模式:访问者模式(C++实现)

    访问者模式通过将对元素的操作与元素本身分离,使得可以在不修改元素类的情况下定义新的操作。 运行结果: 在上述代码中,Visitor是访问者接口,定义了访问具体元素的方法。Element是元素接口,定义了接受访问者访问的方法。ConcreteElementA和ConcreteElementB是具体元素类,实

    2024年02月07日
    浏览(39)
  • 【设计模式与范式:行为型】69 | 访问者模式(下):为什么支持双分派的语言不需要访问者模式?

    上一节课中,我们学习了访问者模式的原理和实现,并且还原了访问者模式诞生的思维过程。总体上来讲,这个模式的代码实现比较难,所以应用场景并不多。从应用开发的角度来说,它的确不是我们学习的重点。 不过,我们前面反复说过,学习我的专栏,并不只是让你掌握

    2024年02月10日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包