行为类模式(十一):访问者(Visitor)

本文介绍了一种设计模式——访问者模式,详细解释了其定义、优缺点及应用场景,并通过一个Java示例展示了如何使用访问者模式对不同类型的对象执行特定的操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

定义

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

UML

优点

  1. 符合单一职责原则:凡是适用访问者模式的场景中,元素类中需要封装在访问者中的操作必定是与元素类本身关系不大且是易变的操作,使用访问者模式一方面符合单一职责原则,另一方面,因为被封装的操作通常来说都是易变的,所以当发生变化时,就可以在不改变元素类本身的前提下,实现对变化部分的扩展;
  2. 扩展性良好:元素类可以通过接受不同的访问者来实现对不同操作的扩展;
  3. 允许你对组合结构加入新的操作,无需改变结构本身;
  4. 想要加入新的操作相对容易;
  5. 访问者所进行的操作,其代码是集中在一起的。

缺点

  1. 会打破组合类的封装;
  2. 因为游走的功能牵涉其中,随意对组合结构的改变就更加困难。

应用场景

  1. 一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作;
  2. 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而你想避免让这些操作“污染”这些对象的类。Visitor模式使得你可以将相关的操作集中起来定义在一个类中;
  3. 当该对象结构被很多应用共享时,用Visitor模式让每个应用仅包含需要用到的操作;
  4. 定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。改变对象结构类需要重定义对所有访问者的接口,这可能需要很大的代价。如果对象结构类经常改变,那么可能还是在这些类中定义这些操作较好。

示例

通过访问者来访问不同对象并打印对应访问者刚兴趣的数据出来。

Java

  1 import java.util.ArrayList;
  2 import java.util.List;
  3 
  4 public class Main
  5 {
  6     public static void main(String[] args)
  7     {
  8         List<Employee> list = new ArrayList<>();
  9         
 10         CommonEmployee zhangSan = new CommonEmployee();
 11         zhangSan.setName("张三");
 12         zhangSan.setSex(Employee.MALE);
 13         zhangSan.setSalary(5000);
 14         zhangSan.setJob("苦逼的码农");
 15         list.add(zhangSan);
 16 
 17         CommonEmployee liSi = new CommonEmployee();
 18         liSi.setName("李四");
 19         liSi.setSex(Employee.FEMALE);
 20         liSi.setSalary(20000);
 21         liSi.setJob("公司里唯一的程序媛");
 22         list.add(liSi);
 23 
 24         Manager wangWu = new Manager();
 25         wangWu.setName("王五");
 26         wangWu.setSex(Employee.MALE);
 27         wangWu.setSalary(66000);
 28         wangWu.setPerformance("业绩基本为负值,不过每次马屁都拍得老板很飘!");
 29         list.add(wangWu);
 30         
 31         for (Employee em : list)
 32         {
 33             em.accept(new Visitor());
 34         }
 35     }
 36 
 37     /**
 38      * 访问者接口
 39      */
 40     public interface IVisitor
 41     {
 42         /**
 43          * 访问普通员工
 44          */
 45         void visit(CommonEmployee commonEmployee);
 46 
 47         /**
 48          * 访问经理
 49          */
 50         void visit(Manager manager);
 51     }
 52 
 53     /**
 54      * 访问者对象
 55      */
 56     public static class Visitor implements IVisitor
 57     {
 58         @Override
 59         public void visit(CommonEmployee commonEmployee)
 60         {
 61             System.out.println(getCommonEmployee(commonEmployee));
 62         }
 63 
 64         @Override
 65         public void visit(Manager manager)
 66         {
 67             System.out.println(getManagerInfo(manager));
 68         }
 69         
 70         private String getBasicInfo(Employee employee)
 71         {
 72             String info = "姓名:" + employee.getName() + "\t";
 73             info += "性别:" + (employee.getSex() == Employee.MALE ? "男" : "女") + "\t";
 74             info += "薪水:" + employee.getSalary() + "\t";
 75             return info;
 76         }
 77         
 78         private String getCommonEmployee(CommonEmployee commonEmployee)
 79         {
 80             String basicInfo = getBasicInfo(commonEmployee);
 81             String otherInfo = "工作:" + commonEmployee.getJob();
 82             return basicInfo + otherInfo;
 83         }
 84         
 85         private String getManagerInfo(Manager manager)
 86         {
 87             String basicInfo = getBasicInfo(manager);
 88             String otherInfo = "业绩:" + manager.getPerformance();
 89             return basicInfo + otherInfo;
 90         }
 91     }
 92 
 93     /**
 94      * 员工基类
 95      */
 96     public static abstract class Employee
 97     {
 98         public final static int MALE = 0;
 99         
100         public final static int FEMALE = 1;
101         
102         private String name;
103         private int sex;
104         private int salary;
105         
106         public String getName()
107         {
108             return name;
109         }
110 
111         public void setName(String name)
112         {
113             this.name = name;
114         }
115 
116         public int getSex()
117         {
118             return sex;
119         }
120 
121         public void setSex(int sex)
122         {
123             this.sex = sex;
124         }
125 
126         public int getSalary()
127         {
128             return salary;
129         }
130 
131         public void setSalary(int salary)
132         {
133             this.salary = salary;
134         }
135 
136         /**
137          * 接受访问者访问
138          */
139         public abstract void accept(IVisitor visitor);
140     }
141 
142     /**
143      * 普通员工
144      */
145     public static class CommonEmployee extends Employee
146     {
147         private String job;
148 
149         public String getJob()
150         {
151             return job;
152         }
153 
154         public void setJob(String job)
155         {
156             this.job = job;
157         }
158 
159         @Override
160         public void accept(IVisitor visitor)
161         {
162             visitor.visit(this);
163         }
164     }
165 
166     /**
167      * 经理
168      */
169     public static class Manager extends Employee
170     {
171         private String performance;
172 
173         public String getPerformance()
174         {
175             return performance;
176         }
177 
178         public void setPerformance(String performance)
179         {
180             this.performance = performance;
181         }
182 
183         @Override
184         public void accept(IVisitor visitor)
185         {
186             visitor.visit(this);
187         }
188     }
189 }
View Code

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值