二十、行为型(访问者模式)

访问者模式(Visitor Pattern)

概念
访问者模式是一种行为型设计模式,允许你在不修改被访问对象的前提下,定义新的操作。它通过将操作封装在访问者类中,从而将操作与对象结构分离。访问者模式非常适合于需要对一组对象进行不同操作的场景。


应用场景

  1. 对象结构稳定:当对象结构相对稳定,但需要为其添加新的操作时,访问者模式可以有效避免修改已有对象的代码。

  2. 复杂的对象结构:在复杂的对象结构中,可能需要对不同的对象执行不同的操作,访问者模式能够简化这些操作的实现。

  3. 需要对对象进行多次操作:当需要对对象进行多种不同操作时,可以使用访问者模式,将每种操作封装在不同的访问者中。

  4. 数据结构遍历:在某些数据结构(如树、图等)的遍历过程中,可以使用访问者模式来处理每个节点的操作。


注意点

  1. 增加新操作的灵活性:访问者模式允许灵活地增加新的操作,但添加新的元素(被访问对象)时,可能需要修改访问者接口,降低了扩展性。

  2. 对象结构的变化:如果对象结构经常变化,使用访问者模式可能会导致维护成本增加,因为每次变化都需要修改访问者的相关代码。

  3. 访问者与被访问者之间的耦合:访问者和被访问者之间的耦合性较强,可能影响到系统的可维护性。


核心要素

  1. Visitor(访问者接口):定义对每种具体元素的访问方法。

  2. ConcreteVisitor(具体访问者):实现访问者接口,定义具体的操作。

  3. Element(元素接口):定义接受访问者的接口。

  4. ConcreteElement(具体元素):实现元素接口,定义具体的被访问者。

  5. ObjectStructure(对象结构):维护一组元素,并提供对元素的遍历。


Java代码完整示例

示例:简单的访问者模式实现

// 访问者接口
interface Visitor {
    
    
    void visit(ConcreteElementA elementA);
    void visit(ConcreteElementB elementB);
}

// 具体访问者
class ConcreteVisitor implements Visitor {
    
    
    @Override
    public void visit(ConcreteElementA elementA) {
    
    
        System.out.println("Visiting ConcreteElementA");
    }

    @Override
    public void visit(ConcreteElementB elementB) {
    
    
        System.out.println("Visiting ConcreteElementB");
    }
}

// 元素接口
interface Element {
    
    
    void accept(Visitor visitor);
}

// 具体元素A
class ConcreteElementA implements Element {
    
    
    @Override
    public void accept(Visitor visitor) {
    
    
        visitor.visit(this);
    }
}

// 具体元素B
class ConcreteElementB implements Element {
    
    
    @Override
    public void accept(Visitor visitor) {
    
    
        visitor.visit(this);
    }
}

// 对象结构
class ObjectStructure {
    
    
    private List<Element> elements = new ArrayList<>();

    public void addElement(Element element) {
    
    
        elements.add(element);
    }

    public void accept(Visitor visitor) {
    
    
        for (Element element : elements) {
    
    
            element.accept(visitor);
        }
    }
}

// 客户端代码
public class VisitorPatternDemo {
    
    
    public static void main(String[] args) {
    
    
        ObjectStructure structure = new ObjectStructure();
        structure.addElement(new ConcreteElementA());
        structure.addElement(new ConcreteElementB());

        ConcreteVisitor visitor = new ConcreteVisitor();
        structure.accept(visitor);
    }
}

输出结果

Visiting ConcreteElementA
Visiting ConcreteElementB

各种变形用法完整示例

  1. 多个具体访问者

    通过定义多个具体访问者来实现不同的操作。

    代码示例:多个访问者

    // 另一个具体访问者
    class AnotherVisitor implements Visitor {
          
          
        @Override
        public void visit(ConcreteElementA elementA) {
          
          
            System.out.println("AnotherVisitor visiting ConcreteElementA");
        }
    
        @Override
        public void visit(ConcreteElementB elementB) {
          
          
            System.out.println("AnotherVisitor visiting ConcreteElementB");
        }
    }
    
    public class MultiVisitorDemo {
          
          
        public static void main(String[] args) {
          
          
            ObjectStructure structure = new ObjectStructure();
            structure.addElement(new ConcreteElementA());
            structure.addElement(new ConcreteElementB());
    
            ConcreteVisitor visitor1 = new ConcreteVisitor();
            structure.accept(visitor1); // 使用第一个访问者
    
            AnotherVisitor visitor2 = new AnotherVisitor();
            structure.accept(visitor2); // 使用第二个访问者
        }
    }
    
  2. 访问者的复杂操作

    访问者可以执行更复杂的操作,比如在访问时修改元素的状态。

    代码示例:复杂操作

    // 具体元素A
    class ConcreteElementA implements Element {
          
          
        private int value;
    
        public ConcreteElementA(int value) {
          
          
            this.value = value;
        }
    
        public int getValue() {
          
          
            return value;
        }
    
        public void setValue(int value) {
          
          
            this.value = value;
        }
    
        @Override
        public void accept(Visitor visitor) {
          
          
            visitor.visit(this);
        }
    }
    
    // 具体访问者:增加值
    class IncrementVisitor implements Visitor {
          
          
        @Override
        public void visit(ConcreteElementA elementA) {
          
          
            int newValue = elementA.getValue() + 1;
            elementA.setValue(newValue);
            System.out.println("Incremented ConcreteElementA value to: " + newValue);
        }
    
        @Override
        public void visit(ConcreteElementB elementB) {
          
          
            // 不做任何操作
        }
    }
    
    public class IncrementVisitorDemo {
          
          
        public static void main(String[] args) {
          
          
            ObjectStructure structure = new ObjectStructure();
            ConcreteElementA elementA = new ConcreteElementA(10);
            structure.addElement(elementA);
            structure.addElement(new ConcreteElementB());
    
            IncrementVisitor incrementVisitor = new IncrementVisitor();
            structure.accept(incrementVisitor); // 增加元素A的值
        }
    }
    
  3. 遍历复杂对象结构

    对于树形结构等复杂对象,可以使用访问者模式进行遍历和操作。

    代码示例:树形结构

    // 树形元素接口
    interface TreeElement extends Element {
          
          
        List<TreeElement> getChildren();
    }
    
    // 具体树形元素
    class TreeNode implements TreeElement {
          
          
        private String name;
        private List<TreeElement> children = new ArrayList<>();
    
        public TreeNode(String name) {
          
          
            this.name = name;
        }
    
        public void addChild(TreeElement child) {
          
          
            children.add(child);
        }
    
        @Override
        public List<TreeElement> getChildren() {
          
          
            return children;
        }
    
        @Override
        public void accept(Visitor visitor) {
          
          
            visitor.visit(this);
            for (TreeElement child : children) {
          
          
                child.accept(visitor);
            }
        }
    
        public String getName() {
          
          
            return name;
        }
    }
    
    // 具体访问者:打印节点名称
    class PrintVisitor implements Visitor {
          
          
        @Override
        public void visit(ConcreteElementA elementA) {
          
          
            // 不做任何操作
        }
    
        @Override
        public void visit(ConcreteElementB elementB) {
          
          
            // 不做任何操作
        }
    
        @Override
        public void visit(TreeNode treeNode) {
          
          
            System.out.println("Visiting TreeNode: " + treeNode.getName());
        }
    }
    
    public class TreeStructureDemo {
          
          
        public static void main(String[] args) {
          
          
            TreeNode root = new TreeNode("Root");
            TreeNode child1 = new TreeNode("Child 1");
            TreeNode child2 = new TreeNode("Child 2");
    
            root.addChild(child1);
            root.addChild(child2);
            child1.addChild(new TreeNode("Child 1.1"));
    
            PrintVisitor printVisitor = new PrintVisitor();
            root.accept(printVisitor); // 遍历树结构
        }
    }
    

通过这些示例,访问者模式的灵活性和应用场景得以体现,可以根据具体需求实现多种变形用法。

猜你喜欢

转载自blog.csdn.net/xiaoqi270620903/article/details/143210245