[Design Pattern] Verhaltensmuster: Visitor


#1
Hallo,

dieser Beitrag erklärt das Verhaltensmuster: Visitor

Java:
package de.tutorials.design.patterns.behavioral;

import java.util.Arrays;
import java.util.Iterator;

public class VisitorExample {

	public static void main(String[] args) {
		Human h = new Human();

		Visitor v = new TraceVisitor();
		v.visit(h);
	}

	static interface Visitor {
		void visit(Human human);

		void visit(Legs legs);

		void visit(Arms arms);

		void visit(Torso torso);

		void visit(Head head);
	}

	static class TraceVisitor implements Visitor {

		@Override
		public void visit(Human human) {
			System.out.println("Visit " + human);
			for (BodyPart bodyPart : human) {
				bodyPart.accept(this);
			}
		}

		@Override
		public void visit(Legs legs) {
			System.out.println("Visit: " + legs);
		}

		@Override
		public void visit(Arms arms) {
			System.out.println("Visit: " + arms);
		}

		@Override
		public void visit(Torso torso) {
			System.out.println("Visit " + torso);
		}

		@Override
		public void visit(Head head) {
			System.out.println("Visit: " + head);
		}
	}

	static class Human implements Iterable<BodyPart> {
		Head head = new Head();
		Legs legs = new Legs();
		Arms arms = new Arms();
		Torso torso = new Torso();

		public Head getHead() {
			return head;
		}

		public Legs getLegs() {
			return legs;
		}

		public Arms getArms() {
			return arms;
		}

		public Torso getTorso() {
			return torso;
		}

		@Override
		public Iterator<BodyPart> iterator() {
			return Arrays.asList(head, torso, arms, legs).iterator();
		}

	}

	static interface BodyPart {
		void accept(Visitor v);
	}

	static class Head implements BodyPart {
		@Override
		public void accept(Visitor v) {
			v.visit(this);
		}
	}

	static class Legs implements BodyPart {
		@Override
		public void accept(Visitor v) {
			v.visit(this);
		}
	}

	static class Arms implements BodyPart {
		@Override
		public void accept(Visitor v) {
			v.visit(this);
		}
	}

	static class Torso implements BodyPart {
		@Override
		public void accept(Visitor v) {
			v.visit(this);
		}
	}
}
Ausgabe:
Code:
Visit de.tutorials.design.patterns.behavioral.VisitorExample$Human@7f423820
Visit: de.tutorials.design.patterns.behavioral.VisitorExample$Head@1b3e02ed
Visit de.tutorials.design.patterns.behavioral.VisitorExample$Torso@4322394
Visit: de.tutorials.design.patterns.behavioral.VisitorExample$Arms@77bdcbb2
Visit: de.tutorials.design.patterns.behavioral.VisitorExample$Legs@4d885088
Gruß Tom
 
#2
Hallo,

hier eine etwas dynamischere Variante des Visitor Patterns bei der der Domain-Code nicht vom Pattern beeinflusst ist:

Java:
package de.tutorials.design.patterns.behavioral;

import java.util.Arrays;
import java.util.Iterator;

public class VisitorExample {

	public static void main(String[] args) {
		Human h = new Human();

		Visitor v = new TraceVisitor();
		v.visit(h);
	}

	static interface Visitor {
		void visit(Human human);
		void visit(Legs legs);
		void visit(Arms arms);
		void visit(Torso torso);
		void visit(Head head);
	}

	static class DynamicVisitor<T> {
		private final static String visitMethodName = "visit";
		
		protected void visit(T element) {
			try {
				getClass().getDeclaredMethod(visitMethodName, element.getClass()).invoke(this, element);
			} catch (Exception e) {
				throw new RuntimeException(e);
			}
		}
	}

	static class TraceVisitor extends DynamicVisitor<BodyPart> implements Visitor {

		@Override
		public void visit(Human human) {
			System.out.println("Visit: " + human);
			for (BodyPart bodyPart : human) {
				visit(bodyPart);
			}
		}

		@Override
		public void visit(Legs legs) {
			System.out.println("Visit: " + legs);
		}

		@Override
		public void visit(Arms arms) {
			System.out.println("Visit: " + arms);
		}

		@Override
		public void visit(Torso torso) {
			System.out.println("Visit: " + torso);
		}

		@Override
		public void visit(Head head) {
			System.out.println("Visit: " + head);
		}
	}

	static interface BodyPart {}
	static class Head implements BodyPart {}
	static class Legs implements BodyPart {}
	static class Arms implements BodyPart {}
	static class Torso implements BodyPart {}
	
	static class Human implements Iterable<BodyPart> {
		Head head = new Head();
		Legs legs = new Legs();
		Arms arms = new Arms();
		Torso torso = new Torso();

		public Head getHead() {
			return head;
		}

		public Legs getLegs() {
			return legs;
		}

		public Arms getArms() {
			return arms;
		}

		public Torso getTorso() {
			return torso;
		}

		@Override
		public Iterator<BodyPart> iterator() {
			return Arrays.asList(head, torso, arms, legs).iterator();
		}
	}
}
Ausgabe:
Code:
Visit: de.tutorials.design.patterns.behavioral.VisitorExample$Human@3c2465e5
Visit: de.tutorials.design.patterns.behavioral.VisitorExample$Head@a2c6f70
Visit: de.tutorials.design.patterns.behavioral.VisitorExample$Torso@6b482747
Visit: de.tutorials.design.patterns.behavioral.VisitorExample$Arms@4e0add57
Visit: de.tutorials.design.patterns.behavioral.VisitorExample$Legs@2b49a2c8
Gruß Tom