首页 > 其他分享 >设计模式(二十三)访问者

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

时间:2024-01-29 14:46:28浏览次数:24  
标签:二十三 元素 workTime 访问 employee 设计模式 public 访问者

一、定义

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

二、描述

访问者模式是一种较为复杂的行为型模式,它包含访问者和被访问元素两个主要组成部分,这些被访问的元素通常具有不同的类型,且不同的访问者可以对它们进行不同的访问操作。例如:处方单中的各种药品信息就是被访问的元素,而划价人员和药房工作人员就是访问者。访问者模式可以使得用户在不修改现有系统的情况下扩展系统的功能,为这些不同类型的元素增加新的操作,包含以下五个角色: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)破坏封装。访问者模式要求访问者对象访问并调用每一个元素对象的操作,这意味着元素对象有时候必须暴露一些自己的内部操作和内部状态,否则无法供访问者访问。

标签:二十三,元素,workTime,访问,employee,设计模式,public,访问者
From: https://www.cnblogs.com/WinterSir/p/17573997.html

相关文章

  • 设计模式:策略模式/状态模式
    设计模式是通用的、可复用的代码设计方案,也可以说是针对某类问题的解决方案,因此,掌握好设计模式,可以帮助我们编写更健壮的代码。wiki中将设计模式分为四类,分别是:创建模式(creationalpatterns)结构模式(structuralpatterns)行为模式(behavioralpatterns)并发模式(concurrencypatt......
  • 《设计模式之禅》读书笔记
    参考  https://zhuanlan.zhihu.com/p/357889775 一、六大设计原则单一职责原则定义:应该有且仅有一个原因引起类的变更。举例:属性和行为拆分,例如setPassword(Stringpassword)和changePassword(Stringpassword)。单一职责原则提出了一个编写程序的标准,用“职责”或“......
  • 设计模式
    1、设计模式七大原则:1)单一职责原则,一个类或者一个方法只负责一项原则2)接口隔离原则,客户端不应该依赖他不需要的接口3)依赖倒转原则,细节依赖抽象(面向接口编程)4)里氏替换原则,子类中尽量不重写父类的方法,可通过聚合、组合解决5)开闭原则,对扩展开放,对修改关闭6)迪米特法则,最少知道原......
  • 设计模式:创建型模式
    文章目录 1.简单工厂模式(SimpleFactory)1.1.定义1.2.结构1.3.时序图1.4.代码实现1.5.优缺点1.6.使用场景1.7.总结2.工厂方法模式(FactoryMethod)2.1.定义2.2.结构2.3.时序图2.4.代码实现2.5.优缺点2.6.使用场景2.7.总结3.抽象工厂模式(AbstractFactory)3.1.......
  • 单例设计模式
    单例设计模式概念单例模式是java中常见的设计模式之一,主要有:懒汉单例模式,饿汉单例模式,还有登记式单例.这边主要讲懒汉和饿汉.单例模式有以下特点.单例类只能有一个实例单例类必须自己创建自己的唯一实例单例;类必须给所有其他对象提供这一实例懒汉设计模式代码public......
  • 设计模式-工厂模式
    前言工厂模式,顾名思义就是我们可以通过一个指定的“工厂”获得需要的“产品”,在设计模式中主要用于抽象对象的创建过程,让用户可以指定自己想要的对象而不必关心对象的实例化过程,这样做的好处是:用户只需通过固定的接口而不是直接去调用类的实例化方法来获得一个对象的实例隐藏......
  • Python设计模式:你的代码真的够优雅吗?
    当涉及到代码优化时,Python作为一种高级编程语言,具有广泛的应用领域和强大的功能。在软件开发中,设计模式是一种被广泛采用的解决问题的方案,它提供了一种在特定情境中重复使用的可行方案。在Python中,有许多设计模式可以用来优化代码。其中两种常见的设计模式是单例模式和工厂模式。......
  • 《设计模式:可复用面向对象软件的基础》PDF
    内容简介本书结合设计实例从面向对象的设计中精选出23个设计模式,总结了面向对象设计中*有价值的经验,并且用简洁可复用的形式表达出来。本书分类描述了一组设计良好、表达清楚的软件设计模式,这些模式在实用环境下特别有用。本书适合大学计算机专业的学生、研究生及相关人......
  • 《设计模式之美》PDF
    内容简介本书结合真实项目案例,从面向对象编程范式、设计原则、代码规范、重构技巧和设计模式5个方面详细介绍如何编写高质量代码。第1章为概述,简单介绍了本书涉及的各个模块,以及各个模块之间的联系;第2章介绍面向对象编程范式;第3章介绍设计原则;第4章介绍代码规范;第5章介绍重构技巧;......
  • 设计模式
    ///<summary>///PLC处理器///</summary>publicinterfaceIPlcHandler{voidRequest(IPlcContextcontext);}///<summary>///PLC的数据上下文///</summary>publicinterfaceIPlcContext{PlcRequestRequest{get;}......