访问者模式(Vistor Pattern)

该文章的最新版本已迁移至个人博客【比特飞】,单击链接 https://www.byteflying.com/archives/431 访问。

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

结构对象是使用访问者模式必备条件,而且这个结构对象必须存在遍历自身各个对象的方法。

角色:

1、抽象访问者(Visitor)

为该对象结构中具体元素角色声明一个访问操作接口。该操作接口的名字和参数标识了发送访问请求给具体访问者的具体元素角色,这样访问者就可以通过该元素角色的特定接口直接访问它;

2、具体访问者(Concrete Visitor)

实现Visitor声明的接口;

3、抽象元素(Element)

定义一个接受访问操作,它以一个访问者(Visitor)作为参数;

4、具体元素(Concrete Element )

实现了抽象元素所定义的接受操作接口;

5、结构对象(Object Structure)

可以提供一个高层接口以允许访问者访问它的元素。

示例:

命名空间VistorPattern中包含Student学生基类充当抽象元素,它的3个实现类Kris、Cherry和Harling分别是我的儿子、女儿和侄女的英文名,它们充当具体元素角色。ITeacher接口充当抽象访问者,而Teacher类充当具体访问者。花名册类Roster充当结构对象。本案例尝试使用老师根据花名册来进行家访这样的场景来讲述访问者模式的使用方法。

namespace VistorPattern
public abstract class Student {

	public string Name { get; protected set; }

	public Student(string name) {
Name = name;
} public abstract void Accept(ITeacher teacher); }

学生基类Student,代表抽象元素。

public class Kris : Student {

	public Kris(string name) : base(name) {

	}

	public override void Accept(ITeacher teacher) {
teacher.Visit(this);
} }

Kris类,代表某一具体学生。

public class Cherry : Student {

	public Cherry(string name) : base(name) {

	}

	public override void Accept(ITeacher teacher) {
teacher.Visit(this);
} }

Cherry类,代表某一具体学生。

public class Harling : Student {

	public Harling(string name) : base(name) {

	}

	public override void Accept(ITeacher teacher) {
teacher.Visit(this);
} }

Harling类,代表某一具体学生。

public interface ITeacher {

	void Visit(Student student);

}

ITeacher接口,代表抽象访问者。

public class Teacher : ITeacher {

	private string _name = null;

	public Teacher(string name) {
_name = name;
} public void Visit(Student student) {
Console.WriteLine($"Mr.{_name} is going to visit {student.Name}'s home. ");
} }

Teacher类,代表具体访问者。

public class Roster {

	public List<Student> Students { get; private set; }

	public Roster() {
Students = new List<Student> {
new Cherry("Cherry"),
new Kris("Kris"),
new Harling("Harling")
};
} }

Roster类,代表花名册,充当结构对象,老师根据这个对象来进行家访。

public class Program {

	public static void Main(string[] args) {
Roster roster = new Roster();
foreach(var student in roster.Students) {
student.Accept(new Teacher("Tony"));
} Console.Read();
} }

以上是调用方的代码,以下是这个案例的输出结果:

Mr.Tony is going to visit Cherry's home.
Mr.Tony is going to visit Kris's home.
Mr.Tony is going to visit Harling's home.

优点:

该文章的最新版本已迁移至个人博客【比特飞】,单击链接 https://www.byteflying.com/archives/431 访问。

1、符合单一职责原则,凡是适用访问者模式的场景中,元素类中需要封装在访问者中的操作必定是与元素类本身关系不大且是易变的操作,使用访问者模式一方面符合单一职责原则,另一方面,因为被封装的操作通常来说都是易变的,所以当发生变化时,就可以在不改变元素类本身的前提下,实现对变化部分的扩展;

2、扩展性良好,元素类可以通过接受不同的访问者来实现对不同操作的扩展。

缺点:

1、增加新的元素类变得困难,每增加一个新的元素意味着要在抽象访问者角色中增加一个新的抽象操作,并在每一个具体访问者类中添加相应的具体操作。

使用场景:

1、一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作;

2、需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而你想避免让这些操作“污染”这些对象的类。Visitor模式使得你可以将相关的操作集中起来 定义在一个类中;

3、当该对象结构被很多应用共享时,用Visitor模式让每个应用仅包含需要用到的操作;

4、定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。改变对象结构类需要重定义对所有访问者的接口,这可能需要很大的代价。如果对象结构类经常改变,那么可能还是在这些类中定义这些操作较好。

最新文章

  1. js生成一个不重复的ID的函数的进化之路
  2. NET中验证控件表达式汇总
  3. java nio 网络框架实现
  4. session_start()一些问题
  5. java 集合(Map3)
  6. android下调试unity3d应用
  7. c++ explicit 用法摘抄
  8. HDU 4333 Revolving Digits 扩展KMP
  9. psy 2
  10. jmeter接口测试实践
  11. Python爬虫之模拟登录微信wechat
  12. centos7下如何隐藏nginx的版本号
  13. 潭州课堂25班:Ph201805201 django 项目 第三十九课 后台 文章发布,图片上传到 FastDFS后端实现 七牛云讲解(课堂笔记)
  14. Java集合类 课后练习
  15. Extjs文件选择器
  16. c语言中pthread的理解和使用
  17. 并查集(模板&amp;典型例题整理)
  18. mysql中用户和权限
  19. Spring与Redis的实现
  20. Impala 加载Hive的UDF

热门文章

  1. DEX文件解析--5、dex方法原型解析
  2. 30个Linux Shell脚本经典案例(上)
  3. Nginx之伪404( root与alias )
  4. [jvm] -- 类加载过程篇
  5. IO、NIO实现简单聊天室,附带问题解析
  6. Linux中profile和bashrc的区别
  7. json:server 本地搭建
  8. nginx--做为负载均衡使用
  9. JSONObject遍历
  10. Python重命名和删除文件