Skip to content

Commit cb2a6fa

Browse files
committed
Added another example of proxy pattern. Announcer from JMock demos by Nat Pryce.
1 parent eb75773 commit cb2a6fa

File tree

17 files changed

+316
-21
lines changed

17 files changed

+316
-21
lines changed

proxy/etc/proxy.png

12.5 KB
Loading

proxy/etc/proxy.ucls

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,59 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<class-diagram version="1.1.8" icons="true" automaticImage="PNG" always-add-relationships="false" generalizations="true"
3-
realizations="true" associations="true" dependencies="false" nesting-relationships="true">
4-
<class id="1" language="java" name="com.iluwatar.proxy.WizardTowerProxy" project="proxy"
5-
file="/proxy/src/main/java/com/iluwatar/proxy/WizardTowerProxy.java" binary="false" corner="BOTTOM_RIGHT">
6-
<position height="142" width="214" x="260" y="438"/>
2+
<class-diagram version="1.1.10" icons="true" automaticImage="PNG" always-add-relationships="false"
3+
generalizations="true" realizations="true" associations="true" dependencies="false" nesting-relationships="true"
4+
router="FAN">
5+
<class id="1" language="java" name="com.iluwatar.proxy.example1.WizardTowerProxy" project="proxy"
6+
file="/proxy/src/main/java/com/iluwatar/proxy/example1/WizardTowerProxy.java" binary="false" corner="BOTTOM_RIGHT">
7+
<position height="-1" width="-1" x="407" y="454"/>
78
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
89
sort-features="false" accessors="true" visibility="true">
910
<attributes public="true" package="true" protected="true" private="true" static="true"/>
1011
<operations public="true" package="true" protected="true" private="true" static="true"/>
1112
</display>
1213
</class>
13-
<class id="2" language="java" name="com.iluwatar.proxy.Wizard" project="proxy"
14-
file="/proxy/src/main/java/com/iluwatar/proxy/Wizard.java" binary="false" corner="BOTTOM_RIGHT">
15-
<position height="124" width="117" x="187" y="274"/>
14+
<class id="2" language="java" name="com.iluwatar.proxy.example1.Wizard" project="proxy"
15+
file="/proxy/src/main/java/com/iluwatar/proxy/example1/Wizard.java" binary="false" corner="BOTTOM_RIGHT">
16+
<position height="-1" width="-1" x="684" y="455"/>
1617
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
1718
sort-features="false" accessors="true" visibility="true">
1819
<attributes public="true" package="true" protected="true" private="true" static="true"/>
1920
<operations public="true" package="true" protected="true" private="true" static="true"/>
2021
</display>
2122
</class>
22-
<class id="3" language="java" name="com.iluwatar.proxy.WizardTower" project="proxy"
23-
file="/proxy/src/main/java/com/iluwatar/proxy/WizardTower.java" binary="false" corner="BOTTOM_RIGHT">
24-
<position height="106" width="130" x="344" y="274"/>
23+
<class id="3" language="java" name="com.iluwatar.proxy.example1.WizardTower" project="proxy"
24+
file="/proxy/src/main/java/com/iluwatar/proxy/example1/WizardTower.java" binary="false" corner="BOTTOM_RIGHT">
25+
<position height="-1" width="-1" x="408" y="217"/>
2526
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
2627
sort-features="false" accessors="true" visibility="true">
2728
<attributes public="true" package="true" protected="true" private="true" static="true"/>
2829
<operations public="true" package="true" protected="true" private="true" static="true"/>
2930
</display>
3031
</class>
31-
<generalization id="4">
32+
<class id="4" language="java" name="com.iluwatar.proxy.example1.App" project="proxy"
33+
file="/proxy/src/main/java/com/iluwatar/proxy/example1/App.java" binary="false" corner="BOTTOM_RIGHT">
34+
<position height="-1" width="-1" x="141" y="455"/>
35+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
36+
sort-features="false" accessors="true" visibility="true">
37+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
38+
<operations public="true" package="true" protected="true" private="true" static="true"/>
39+
</display>
40+
</class>
41+
<dependency id="5">
42+
<end type="SOURCE" refId="4"/>
43+
<end type="TARGET" refId="1"/>
44+
</dependency>
45+
<dependency id="6">
46+
<end type="SOURCE" refId="3"/>
47+
<end type="TARGET" refId="2"/>
48+
</dependency>
49+
<generalization id="7">
3250
<end type="SOURCE" refId="1"/>
3351
<end type="TARGET" refId="3"/>
3452
</generalization>
53+
<dependency id="8">
54+
<end type="SOURCE" refId="1"/>
55+
<end type="TARGET" refId="2"/>
56+
</dependency>
3557
<classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
3658
sort-features="false" accessors="true" visibility="true">
3759
<attributes public="true" package="true" protected="true" private="true" static="true"/>

proxy/src/main/java/com/iluwatar/proxy/App.java renamed to proxy/src/main/java/com/iluwatar/proxy/example1/App.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2121
* THE SOFTWARE.
2222
*/
23-
package com.iluwatar.proxy;
23+
package com.iluwatar.proxy.example1;
2424

2525
/**
2626
*

proxy/src/main/java/com/iluwatar/proxy/Wizard.java renamed to proxy/src/main/java/com/iluwatar/proxy/example1/Wizard.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2121
* THE SOFTWARE.
2222
*/
23-
package com.iluwatar.proxy;
23+
package com.iluwatar.proxy.example1;
2424

2525
/**
2626
*

proxy/src/main/java/com/iluwatar/proxy/WizardTower.java renamed to proxy/src/main/java/com/iluwatar/proxy/example1/WizardTower.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2121
* THE SOFTWARE.
2222
*/
23-
package com.iluwatar.proxy;
23+
package com.iluwatar.proxy.example1;
2424

2525
/**
2626
*

proxy/src/main/java/com/iluwatar/proxy/WizardTowerProxy.java renamed to proxy/src/main/java/com/iluwatar/proxy/example1/WizardTowerProxy.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2121
* THE SOFTWARE.
2222
*/
23-
package com.iluwatar.proxy;
23+
package com.iluwatar.proxy.example1;
2424

2525
/**
2626
*
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package com.iluwatar.proxy.example2;
2+
3+
import java.lang.reflect.InvocationTargetException;
4+
import java.lang.reflect.Method;
5+
import java.lang.reflect.Proxy;
6+
import java.util.List;
7+
import java.util.concurrent.CopyOnWriteArrayList;
8+
9+
public class Announcer {
10+
11+
private HealthMonitor proxy;
12+
private List<HealthMonitor> listeners = new CopyOnWriteArrayList<>();
13+
14+
public Announcer(Class<HealthMonitor> listenerType) {
15+
proxy = createProxy(listenerType);
16+
}
17+
18+
private HealthMonitor createProxy(Class<HealthMonitor> listenerType) {
19+
return listenerType.cast(Proxy.newProxyInstance(listenerType.getClassLoader(),
20+
new Class<?>[] {listenerType}, (proxy, method, args) -> {
21+
invokeAll(method, args);
22+
return null;
23+
}));
24+
}
25+
26+
private void invokeAll(Method method, Object[] args) {
27+
for (HealthMonitor listener : listeners) {
28+
try {
29+
method.invoke(listener, args);
30+
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
31+
e.printStackTrace();
32+
}
33+
}
34+
}
35+
36+
public void registerListener(HealthMonitor listener) {
37+
listeners.add(listener);
38+
}
39+
40+
public HealthMonitor announce() {
41+
return proxy;
42+
}
43+
44+
public void removeListener(HealthMonitor listener) {
45+
listeners.remove(listener);
46+
}
47+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package com.iluwatar.proxy.example2;
2+
3+
import java.util.HashMap;
4+
import java.util.Map;
5+
import java.util.Map.Entry;
6+
7+
/**
8+
* An application representing a health monitoring system. Endpoints such as TCP connections, UDP
9+
* connections, DB connections keep fluctuating and may get disconnected. To monitor the health of
10+
* these endpoints user can attach health monitors to the endpoint and when the status of the
11+
* connectivity changes the health monitors are notified of the changes.
12+
*
13+
* The class that implements the Proxy pattern is {@link Announcer}.
14+
*
15+
* @see Announcer
16+
*
17+
* @author npathai
18+
*
19+
*/
20+
public class App {
21+
22+
public static void main(String[] args) {
23+
24+
EndPoint endPoint = new EndPoint("TCP Endpoint");
25+
ConsoleMonitor consoleMonitor = new ConsoleMonitor();
26+
HealthCounter counter = new HealthCounter();
27+
endPoint.addMonitor(consoleMonitor);
28+
endPoint.addMonitor(counter);
29+
30+
endPoint.connected();
31+
endPoint.disconnect();
32+
endPoint.connected();
33+
endPoint.disconnect();
34+
endPoint.connected();
35+
36+
counter.printCounters();
37+
}
38+
39+
private static class ConsoleMonitor implements HealthMonitor {
40+
41+
@Override
42+
public void disconnected(EndPoint endPoint) {
43+
System.out.println(endPoint + " is disconnected.");
44+
}
45+
46+
@Override
47+
public void connected(EndPoint endPoint) {
48+
System.out.println(endPoint + " is connected");
49+
}
50+
}
51+
52+
private static class HealthCounter implements HealthMonitor {
53+
private Map<String, Health> endPointNameToHealth = new HashMap<>();
54+
55+
private class Health {
56+
private boolean connected;
57+
private int disconnectedCount = 0;
58+
private int connectedCount = 0;
59+
}
60+
61+
@Override
62+
public void disconnected(EndPoint endPoint) {
63+
Health health = endPointNameToHealth.get(endPoint.getName());
64+
if (health == null) {
65+
health = new Health();
66+
endPointNameToHealth.put(endPoint.getName(), health);
67+
}
68+
health.connected = false;
69+
health.disconnectedCount++;
70+
}
71+
72+
@Override
73+
public void connected(EndPoint endPoint) {
74+
Health health = endPointNameToHealth.get(endPoint.getName());
75+
if (health == null) {
76+
health = new Health();
77+
endPointNameToHealth.put(endPoint.getName(), health);
78+
}
79+
health.connected = true;
80+
health.connectedCount++;
81+
}
82+
83+
public void printCounters() {
84+
for (Entry<String, Health> entry : endPointNameToHealth.entrySet()) {
85+
System.out.println(String.format("EndPoint: %s, Connected: %s, Connected Count: %d, Disconnected Count: %d",
86+
entry.getKey(), entry.getValue().connected, entry.getValue().connectedCount,
87+
entry.getValue().disconnectedCount));
88+
}
89+
}
90+
}
91+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.iluwatar.proxy.example2;
2+
3+
public class EndPoint {
4+
5+
private final String name;
6+
private final Announcer healthMonitors = new Announcer(HealthMonitor.class);
7+
8+
public EndPoint(String name) {
9+
this.name = name;
10+
}
11+
12+
public void addMonitor(HealthMonitor monitor) {
13+
healthMonitors.registerListener(monitor);
14+
}
15+
16+
public void disconnect() {
17+
healthMonitors.announce().disconnected(this);
18+
}
19+
20+
public void connected() {
21+
healthMonitors.announce().connected(this);
22+
}
23+
24+
public String getName() {
25+
return name;
26+
}
27+
28+
@Override
29+
public String toString() {
30+
return name;
31+
}
32+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.iluwatar.proxy.example2;
2+
3+
public interface HealthMonitor {
4+
5+
void disconnected(EndPoint endPoint);
6+
7+
void connected(EndPoint endPoint);
8+
9+
}

0 commit comments

Comments
 (0)