概念:
在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。
意图:
主要将数据结构与数据操作分离。
主要解决:
稳定的数据结构和易变的操作耦合问题。
优点:
- 符合单一职责原则。
- 优秀的扩展性。
- 灵活性。
缺点:
- 具体元素对访问者公布细节,违反了迪米特原则。
- 具体元素变更比较困难。
- 违反了依赖倒置原则,依赖了具体类,没有依赖抽象。
实现类图
访问者模式包含以下主要角色。
抽象访问者(Visitor)角色: 定义一个访问具体元素的接口,为每个具体元素类对应一个访问操作,该操作中的参数类型标识了被访问的具体元素。
public abstract class 电影
{
abstract public void accept(顾客 n);
abstract public void 播放电影();
}
具体访问者(ConcreteVisitor)角色: 实现抽象访问者角色中声明的各个访问操作,确定访问者访问一个元素时该做什么。
using System;
public class 爱国片 : 电影
{
public override void accept(顾客 n)
{
n.看电影(this);
}
public override void 播放电影()
{
Console.WriteLine("电影院播放爱国片电影!");
}
}
using System;
public class 爱情片 : 电影
{
public override void accept(顾客 n)
{
n.看电影(this);
}
public override void 播放电影()
{
Console.WriteLine("电影院播放爱情片电影!");
}
}
抽象元素(Element)角色: 声明一个包含接受操作 accept() 的接口,被接受的访问者对象作为 accept() 方法的参数。
public abstract class 顾客
{
abstract public void 看电影(爱国片 m);
abstract public void 看电影(爱情片 m);
}
具体元素(ConcreteElement)角色: 实现抽象元素角色提供的 accept() 操作。
using System;
public class 老人 : 顾客
{
public override void 看电影(爱国片 m)
{
Console.Write("老人看: ");
m.播放电影();
}
public override void 看电影(爱情片 m)
{
Console.Write("老人看: ");
m.播放电影();
}
}
using System;
public class 学生 : 顾客
{
public override void 看电影(爱国片 m)
{
Console.Write("学生看: ");
m.播放电影();
}
public override void 看电影(爱情片 m)
{
Console.Write("学生看: ");
m.播放电影();
}
}
对象结构(Object Structure)角色: 是一个包含元素角色的容器,提供让访问者对象遍历容器中的所有元素的方法。
using System.Collections.Generic;
class 电影库
{
private List<电影> list = new List<电影>();
//观看当前电影库里所有的电影
public void accept(顾客 m)
{
foreach (电影 n in list)
{
n.accept(m);
}
}
//添加方法
public void add(电影 m)
{
list.Add(m);
}
}
测试:
using System;
class Program
{
static void Main(string[] args)
{
电影库 m = new 电影库();
m.add(new 爱国片());
m.add(new 爱情片());
顾客 n = new 老人();
m.accept(n);
Console.WriteLine(" ");
n = new 学生();
n.看电影(new 爱国片());
Console.Read();
}
}
输出示例
设计模式------首页