Skip to content

Commit 7add7b8

Browse files
authored
Merge branch 'master' into ambassador
2 parents 0453bf9 + c7f9266 commit 7add7b8

25 files changed

+1022
-0
lines changed

acyclic-visitor/README.md

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
---
2+
layout: pattern
3+
title: Acyclic Visitor
4+
folder: acyclic-visitor
5+
permalink: /patterns/acyclic-visitor/
6+
categories: Behavioral
7+
tags:
8+
- Java
9+
- Difficulty-Intermediate
10+
---
11+
12+
![alt text](./etc/acyclic-visitor.png "Acyclic Visitor")
13+
14+
## Intent
15+
Allow new functions to be added to existing class hierarchies without affecting those hierarchies, and without creating the troublesome dependency cycles that are inherent to the GOF VISITOR Pattern.
16+
17+
## Applicability
18+
This pattern can be used:
19+
* When you need to add a new function to an existing hierarchy without the need to alter or affect that hierarchy.
20+
* When there are functions that operate upon a hierarchy, but which do not belong in the hierarchy itself. e.g. the ConfigureForDOS / ConfigureForUnix / ConfigureForX issue.
21+
* When you need to perform very different operations on an object depending upon its type.
22+
* When the visited class hierarchy will be frequently extended with new derivatives of the Element class.
23+
* When the recompilation, relinking, retesting or redistribution of the derivatives of Element is very expensive.
24+
25+
## Consequences
26+
The good:
27+
* No dependency cycles between class hierarchies.
28+
* No need to recompile all the visitors if a new one is added.
29+
* Does not cause compilation failure in existing visitors if class hierarchy has a new member.
30+
31+
The bad:
32+
* Violates the principle of least surprise or Liskov's Substitution principle by showing that it can accept all visitors but actually only being interested in particular visitors.
33+
* Parallel hierarchy of visitors has to be created for all members in visitable class hierarchy.
34+
35+
## Related patterns
36+
* [Visitor Pattern](../visitor/README.md)
37+
38+
## Credits
39+
* [Acyclic Visitor](http://condor.depaul.edu/dmumaugh/OOT/Design-Principles/acv.pdf)
+115
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<class-diagram version="1.2.2" icons="true" always-add-relationships="false" generalizations="true" realizations="true"
3+
associations="true" dependencies="false" nesting-relationships="true" router="FAN">
4+
<interface id="1" language="java" name="com.iluwatar.acyclicvisitor.ModemVisitor" project="acyclic-visitor"
5+
file="/acyclic-visitor/src/main/java/com/iluwatar/acyclicvisitor/ModemVisitor.java" binary="false"
6+
corner="BOTTOM_RIGHT">
7+
<position height="-1" width="-1" x="860" y="67"/>
8+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
9+
sort-features="false" accessors="true" visibility="true">
10+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
11+
<operations public="true" package="true" protected="true" private="true" static="true"/>
12+
</display>
13+
</interface>
14+
<class id="2" language="java" name="com.iluwatar.acyclicvisitor.Modem" project="acyclic-visitor"
15+
file="/acyclic-visitor/src/main/java/com/iluwatar/acyclicvisitor/Modem.java" binary="false" corner="BOTTOM_RIGHT">
16+
<position height="-1" width="-1" x="327" y="77"/>
17+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
18+
sort-features="false" accessors="true" visibility="true">
19+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
20+
<operations public="true" package="true" protected="true" private="true" static="true"/>
21+
</display>
22+
</class>
23+
<class id="3" language="java" name="com.iluwatar.acyclicvisitor.ConfigureForUnixVisitor" project="acyclic-visitor"
24+
file="/acyclic-visitor/src/main/java/com/iluwatar/acyclicvisitor/ConfigureForUnixVisitor.java" binary="false"
25+
corner="BOTTOM_RIGHT">
26+
<position height="124" width="196" x="647" y="225"/>
27+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
28+
sort-features="false" accessors="true" visibility="true">
29+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
30+
<operations public="true" package="true" protected="true" private="true" static="true"/>
31+
</display>
32+
</class>
33+
<class id="4" language="java" name="com.iluwatar.acyclicvisitor.Zoom" project="acyclic-visitor"
34+
file="/acyclic-visitor/src/main/java/com/iluwatar/acyclicvisitor/Zoom.java" binary="false" corner="BOTTOM_RIGHT">
35+
<position height="-1" width="-1" x="203" y="305"/>
36+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
37+
sort-features="false" accessors="true" visibility="true">
38+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
39+
<operations public="true" package="true" protected="true" private="true" static="true"/>
40+
</display>
41+
</class>
42+
<interface id="5" language="java" name="com.iluwatar.acyclicvisitor.HayesVisitor" project="acyclic-visitor"
43+
file="/acyclic-visitor/src/main/java/com/iluwatar/acyclicvisitor/HayesVisitor.java" binary="false"
44+
corner="BOTTOM_RIGHT">
45+
<position height="-1" width="-1" x="1019" y="468"/>
46+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
47+
sort-features="false" accessors="true" visibility="true">
48+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
49+
<operations public="true" package="true" protected="true" private="true" static="true"/>
50+
</display>
51+
</interface>
52+
<interface id="6" language="java" name="com.iluwatar.acyclicvisitor.ZoomVisitor" project="acyclic-visitor"
53+
file="/acyclic-visitor/src/main/java/com/iluwatar/acyclicvisitor/ZoomVisitor.java" binary="false"
54+
corner="BOTTOM_RIGHT">
55+
<position height="-1" width="-1" x="758" y="467"/>
56+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
57+
sort-features="false" accessors="true" visibility="true">
58+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
59+
<operations public="true" package="true" protected="true" private="true" static="true"/>
60+
</display>
61+
</interface>
62+
<class id="7" language="java" name="com.iluwatar.acyclicvisitor.Hayes" project="acyclic-visitor"
63+
file="/acyclic-visitor/src/main/java/com/iluwatar/acyclicvisitor/Hayes.java" binary="false" corner="BOTTOM_RIGHT">
64+
<position height="-1" width="-1" x="479" y="307"/>
65+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
66+
sort-features="false" accessors="true" visibility="true">
67+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
68+
<operations public="true" package="true" protected="true" private="true" static="true"/>
69+
</display>
70+
</class>
71+
<class id="8" language="java" name="com.iluwatar.acyclicvisitor.ConfigureForDosVisitor" project="acyclic-visitor"
72+
file="/acyclic-visitor/src/main/java/com/iluwatar/acyclicvisitor/ConfigureForDosVisitor.java" binary="false"
73+
corner="BOTTOM_RIGHT">
74+
<position height="142" width="192" x="883" y="225"/>
75+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
76+
sort-features="false" accessors="true" visibility="true">
77+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
78+
<operations public="true" package="true" protected="true" private="true" static="true"/>
79+
</display>
80+
</class>
81+
<generalization id="9">
82+
<end type="SOURCE" refId="7"/>
83+
<end type="TARGET" refId="2"/>
84+
</generalization>
85+
<realization id="10">
86+
<end type="SOURCE" refId="8"/>
87+
<end type="TARGET" refId="6"/>
88+
</realization>
89+
<realization id="11">
90+
<end type="SOURCE" refId="8"/>
91+
<end type="TARGET" refId="5"/>
92+
</realization>
93+
<realization id="12">
94+
<end type="SOURCE" refId="3"/>
95+
<end type="TARGET" refId="6"/>
96+
</realization>
97+
<realization id="13">
98+
<end type="SOURCE" refId="3"/>
99+
<end type="TARGET" refId="1"/>
100+
</realization>
101+
<realization id="14">
102+
<end type="SOURCE" refId="8"/>
103+
<end type="TARGET" refId="1"/>
104+
</realization>
105+
<generalization id="15">
106+
<end type="SOURCE" refId="4"/>
107+
<end type="TARGET" refId="2"/>
108+
</generalization>
109+
<classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
110+
sort-features="false" accessors="true" visibility="true">
111+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
112+
<operations public="true" package="true" protected="true" private="true" static="true"/>
113+
</classifier-display>
114+
<association-display labels="true" multiplicity="true"/>
115+
</class-diagram>
26 KB
Loading

acyclic-visitor/pom.xml

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<!--
2+
3+
The MIT License
4+
Copyright (c) 2014 Ilkka Seppälä
5+
6+
Permission is hereby granted, free of charge, to any person obtaining a copy
7+
of this software and associated documentation files (the "Software"), to deal
8+
in the Software without restriction, including without limitation the rights
9+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
copies of the Software, and to permit persons to whom the Software is
11+
furnished to do so, subject to the following conditions:
12+
13+
The above copyright notice and this permission notice shall be included in
14+
all copies or substantial portions of the Software.
15+
16+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
THE SOFTWARE.
23+
24+
-->
25+
<project xmlns="http://maven.apache.org/POM/4.0.0"
26+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
27+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
28+
<modelVersion>4.0.0</modelVersion>
29+
30+
<parent>
31+
<groupId>com.iluwatar</groupId>
32+
<artifactId>java-design-patterns</artifactId>
33+
<version>1.20.0-SNAPSHOT</version>
34+
</parent>
35+
36+
<artifactId>acyclic-visitor</artifactId>
37+
38+
<properties>
39+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
40+
<maven.compiler.source>1.8</maven.compiler.source>
41+
<maven.compiler.target>1.8</maven.compiler.target>
42+
</properties>
43+
44+
<dependencies>
45+
<!-- https://mvnrepository.com/artifact/org.assertj/assertj-core -->
46+
<dependency>
47+
<groupId>org.assertj</groupId>
48+
<artifactId>assertj-core</artifactId>
49+
<version>3.9.1</version>
50+
<scope>test</scope>
51+
</dependency>
52+
<!-- https://mvnrepository.com/artifact/uk.org.lidalia/slf4j-test -->
53+
<dependency>
54+
<groupId>uk.org.lidalia</groupId>
55+
<artifactId>slf4j-test</artifactId>
56+
<version>1.0.0</version>
57+
<scope>test</scope>
58+
</dependency>
59+
<dependency>
60+
<groupId>org.junit.jupiter</groupId>
61+
<artifactId>junit-jupiter-api</artifactId>
62+
<scope>test</scope>
63+
</dependency>
64+
<dependency>
65+
<groupId>org.junit.jupiter</groupId>
66+
<artifactId>junit-jupiter-engine</artifactId>
67+
<scope>test</scope>
68+
</dependency>
69+
<dependency>
70+
<groupId>org.mockito</groupId>
71+
<artifactId>mockito-all</artifactId>
72+
<version>1.9.5</version>
73+
<scope>test</scope>
74+
</dependency>
75+
</dependencies>
76+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/**
2+
* The MIT License
3+
* Copyright (c) 2014-2016 Ilkka Seppälä
4+
*
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be included in
13+
* all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
* THE SOFTWARE.
22+
*/
23+
package com.iluwatar.acyclicvisitor;
24+
25+
/**
26+
* All ModemVisitor interface extends all visitor interfaces
27+
*/
28+
public interface AllModemVisitor extends ModemVisitor, ZoomVisitor, HayesVisitor{
29+
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/**
2+
* The MIT License
3+
* Copyright (c) 2014-2016 Ilkka Seppälä
4+
*
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be included in
13+
* all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
* THE SOFTWARE.
22+
*/
23+
package com.iluwatar.acyclicvisitor;
24+
25+
/**
26+
* The Acyclic Visitor pattern allows new functions to be added to existing class
27+
* hierarchies without affecting those hierarchies, and without creating the dependency
28+
* cycles that are inherent to the GoF Visitor pattern, by making the Visitor base class
29+
* degenerate
30+
* <p>
31+
* In this example the visitor base class is {@link ModemVisitor}. The base class of the
32+
* visited hierarchy is {@link Modem} and has two children {@link Hayes} and {@link Zoom}
33+
* each one having its own visitor interface {@link HayesVisitor} and {@link ZoomVisitor}
34+
* respectively. {@link ConfigureForUnixVisitor} and {@link ConfigureForDosVisitor}
35+
* implement each derivative's visit method only if it is required
36+
*/
37+
public class App {
38+
39+
/**
40+
* Program's entry point
41+
*/
42+
43+
public static void main(String[] args) {
44+
ConfigureForUnixVisitor conUnix = new ConfigureForUnixVisitor();
45+
ConfigureForDosVisitor conDos = new ConfigureForDosVisitor();
46+
47+
Zoom zoom = new Zoom();
48+
Hayes hayes = new Hayes();
49+
50+
hayes.accept(conDos); // Hayes modem with Unix configurator
51+
zoom.accept(conDos); // Zoom modem with Dos configurator
52+
hayes.accept(conUnix); // Hayes modem with Unix configurator
53+
zoom.accept(conUnix); // Zoom modem with Unix configurator
54+
}
55+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/**
2+
* The MIT License
3+
* Copyright (c) 2014-2016 Ilkka Seppälä
4+
*
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be included in
13+
* all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
* THE SOFTWARE.
22+
*/
23+
package com.iluwatar.acyclicvisitor;
24+
25+
import org.slf4j.Logger;
26+
import org.slf4j.LoggerFactory;
27+
28+
/**
29+
* ConfigureForDosVisitor class implements both zoom's and hayes' visit method
30+
* for Dos manufacturer
31+
*/
32+
public class ConfigureForDosVisitor implements AllModemVisitor {
33+
34+
private static final Logger LOGGER = LoggerFactory.getLogger(ConfigureForDosVisitor.class);
35+
36+
public void visit(Hayes hayes) {
37+
LOGGER.info(hayes + " used with Dos configurator.");
38+
}
39+
40+
public void visit(Zoom zoom) {
41+
LOGGER.info(zoom + " used with Dos configurator.");
42+
}
43+
}

0 commit comments

Comments
 (0)