-
Notifications
You must be signed in to change notification settings - Fork 1
/
HandmadeEvents.java
116 lines (96 loc) · 2.69 KB
/
HandmadeEvents.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// Getting away from idea of observers/observables
package behavioral.observer.events;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
// Encapsulating idea of something happy;
class Event<TArgs>
{
private int count = 0;
private Map<Integer, Consumer<TArgs>>
handlers = new HashMap<>();
public Subscription addHandler(Consumer<TArgs> handler)
{
int i = count;
handlers.put(count++, handler);
return new Subscription(this, i);
}
public void fire(TArgs args)
{
for(Consumer<TArgs> handler : handlers.values())
{
handler.accept(args);
}
}
// Memento approach
public class Subscription implements AutoCloseable
{
private Event<TArgs> event;
private int id; // index into the handlers hashmap
public Subscription(Event<TArgs> event, int id) {
this.event = event;
this.id = id;
}
@Override
public void close() /*throws Exception*/
{
event.handlers.remove(id); // remove subscription by finding id
}
}
}
// Notification object
class PropertyChangedEventArgs
{
public Object source;
public String propertyName;
public PropertyChangedEventArgs(Object source, String propertyName) {
this.source = source;
this.propertyName = propertyName;
}
}
class Person
{
// advertising an event on Person that can be triggered, and if you want notifications, you can subscribe to it
public Event<PropertyChangedEventArgs>
propertyChanged = new Event<>();
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
if (this.age == age) return;
boolean oldCanVote = getCanVote();
this.age = age;
propertyChanged.fire(new PropertyChangedEventArgs(
this, "age"
));
if (oldCanVote != getCanVote())
{
propertyChanged.fire(new PropertyChangedEventArgs(
this, "can vote."
));
}
}
// This method depends on age.
public boolean getCanVote()
{
return age >= 18;
}
}
class HandmadeEventsDemo
{
public static void main(String[] args) {
Person person = new Person();
// Event here
Event<PropertyChangedEventArgs>.Subscription sub
= person.propertyChanged.addHandler(x ->
{
System.out.println("Person's "
+ x.propertyName + " has changed to " + person.getAge());
});
person.setAge(17);
person.setAge(18);
sub.close(); // unsubscribes
person.setAge(19);
}
}