深究设计模式之-访问者模式

285 阅读3分钟

访问者模式(Visitor Pattern)是一种行为型设计模式,其主要目的是将算法与对象结构分离,使得可以在不修改对象结构的前提下定义新的操作。访问者模式通过在对象结构中添加一个接受访问者的接口,使得访问者可以通过这个接口访问对象结构中的元素,并对其执行操作。

主要角色:

  1. 访问者(Visitor): 定义了对每个具体元素(ConcreteElement)的访问操作接口。

  2. 具体访问者(Concrete Visitor): 实现了访问者接口,对每个具体元素提供具体的访问操作。

  3. 元素(Element): 定义了接受访问者的接口,通常包含一个接受操作,接收一个访问者作为参数。

  4. 具体元素(Concrete Element): 实现了元素接口,提供了接受访问者的具体实现。

  5. 对象结构(Object Structure): 包含了具体元素的集合,可以是一个列表、数组或其他数据结构,通常提供一个接受访问者的方法,用于遍历集合中的元素。

通俗点说,访问者模式就像我们去博物馆参观一样。博物馆的展品是数据结构,而我们作为游客就是访问者。博物馆的导览员(访问者)知道如何向我们介绍展品,但展品本身并不需要知道导览员的存在。如果有新的导览员(新的访问者)出现,他们只需要知道如何与展品交互,而无需修改展品的内部结构。

在程序设计中,这种模式的好处是,当我们有一个稳定的数据结构,但可能有多种不同的操作时,我们可以通过添加新的访问者而不改变数据结构的情况下,灵活地扩展系统功能。这使得系统更容易维护和扩展。

示例:

举一个简化的计算机设备管理系统的例子,其中有不同类型的设备(如鼠标、键盘、显示器),我们可以通过访问者模式实现对这些设备的管理。

// 访问者接口
interface ComputerPartVisitor {
    void visit(Mouse mouse);
    void visit(Keyboard keyboard);
    void visit(Monitor monitor);
}

// 具体访问者 - 设备显示
class ComputerPartDisplayVisitor implements ComputerPartVisitor {
    @Override
    public void visit(Mouse mouse) {
        System.out.println("Displaying Mouse");
    }

    @Override
    public void visit(Keyboard keyboard) {
        System.out.println("Displaying Keyboard");
    }

    @Override
    public void visit(Monitor monitor) {
        System.out.println("Displaying Monitor");
    }
}

// 元素接口
interface ComputerPart {
    void accept(ComputerPartVisitor visitor);
}

// 具体元素 - 鼠标
class Mouse implements ComputerPart {
    @Override
    public void accept(ComputerPartVisitor visitor) {
        visitor.visit(this);
    }
}

// 具体元素 - 键盘
class Keyboard implements ComputerPart {
    @Override
    public void accept(ComputerPartVisitor visitor) {
        visitor.visit(this);
    }
}

// 具体元素 - 显示器
class Monitor implements ComputerPart {
    @Override
    public void accept(ComputerPartVisitor visitor) {
        visitor.visit(this);
    }
}

// 对象结构
class Computer implements ComputerPart {
    private ComputerPart[] parts;

    public Computer() {
        this.parts = new ComputerPart[]{new Mouse(), new Keyboard(), new Monitor()};
    }

    @Override
    public void accept(ComputerPartVisitor visitor) {
        for (ComputerPart part : parts) {
            part.accept(visitor);
        }
        visitor.visit(this);
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        ComputerPartVisitor displayVisitor = new ComputerPartDisplayVisitor();
        Computer computer = new Computer();
        computer.accept(displayVisitor);
    }
}

image.png

在这个例子中,ComputerPart 是元素接口,定义了接受访问者的方法。MouseKeyboardMonitor 是具体元素,实现了元素接口,并在 accept 方法中调用访问者的具体访问方法。ComputerPartVisitor 是访问者接口,定义了对每个具体元素的访问操作。ComputerPartDisplayVisitor 是具体访问者,实现了访问者接口,并提供了对设备的显示操作。Computer 是对象结构,包含了设备的集合,并在 accept 方法中遍历集合中的元素,调用它们的 accept 方法。

通过访问者模式,可以轻松地添加新的访问者,而不需要修改对象结构的代码,使得我们的系统更加灵活和易于扩展。