Hallo allemaal,
Gisteren stuitte ik tegen een designprobleem, en tot nu toe heb ik hiervoor nog geen mooie en vooral handige oplossing gevonden.
Stel je hebt volgende interface (vergelijkbaar met java.util.Collection):
Veel algoritmen (bijvoorbeeld het sorteren van een collectie) hebben maar een subset van deze functies nodig. Daarom is het een goed idee om de interface te splitsen in kleinere interfaces (mensen met ervaring met generic programming, bv. C++ STL, zullen dit wel herkennen in concepten en models van concepten):
Nu komt mijn probleem. Stel je hebt een functie die een collectie aanvaardt (input) en een collectie returnt (output). Normaliter wil je dat de output van hetzelfde type is dan de input. Bijvoorbeeld, als een inputcollectie updatable en iterable is, wil je dat je outputcollectie dat ook is. Hieronder heb ik een functie, decorateCollection(MyCollection c), geschreven die de inputcollectie 'verkapt' in een collectie van hetzelfde type, en deze returnt.
Het probleem is dat ik nu telkens het type van de inputcollectie moet controleren, om een collectie van hetzelfde type aan te kunnen maken. Dit is niet handig, en zeker niet praktisch bij een groter aantal interfaces. Het aantal combinaties is exponentieel!
Mijn vraag is nu: kan dit beter? Ik zit er al een tijdje naar te staren, maar ik denk dat ik hier op 1 van de beperkingen van Java stuit.
Gisteren stuitte ik tegen een designprobleem, en tot nu toe heb ik hiervoor nog geen mooie en vooral handige oplossing gevonden.
Stel je hebt volgende interface (vergelijkbaar met java.util.Collection):
Java:
1
2
3
4
5
6
7
8
9
10
| private interface MyCollection { public boolean isEmpty(); public int size(); public void clear(); public boolean add(Object o); public boolean remove(Object o); public Iterator iterator(); } |
Veel algoritmen (bijvoorbeeld het sorteren van een collectie) hebben maar een subset van deze functies nodig. Daarom is het een goed idee om de interface te splitsen in kleinere interfaces (mensen met ervaring met generic programming, bv. C++ STL, zullen dit wel herkennen in concepten en models van concepten):
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| private interface MyCollection { public boolean isEmpty(); public int size(); } private interface MyUpdatableCollection extends MyCollection { public void clear(); public boolean add(Object o); public boolean remove(Object o); } private interface MyIterableCollection extends MyCollection { public Iterator iterator(); } |
Nu komt mijn probleem. Stel je hebt een functie die een collectie aanvaardt (input) en een collectie returnt (output). Normaliter wil je dat de output van hetzelfde type is dan de input. Bijvoorbeeld, als een inputcollectie updatable en iterable is, wil je dat je outputcollectie dat ook is. Hieronder heb ik een functie, decorateCollection(MyCollection c), geschreven die de inputcollectie 'verkapt' in een collectie van hetzelfde type, en deze returnt.
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
| public MyCollection decorateCollection(MyCollection c) { boolean updatable = c instanceof MyUpdatableCollection; boolean iterable = c instanceof MyIterableCollection; if (updatable && iterable) return new _UpdatableAndIterable(c); else if (updatable) return new _Updatable(c); else if (iterable) return new _Iterable(c); else return new _None(c); } public class _UpdatableAndIterable implements MyUpdatableCollection, MyIterableCollection { MyCollection c; public _UpdatableAndIterable(MyCollection c) { this.c = c; } public void clear() { ((MyUpdatableCollection) c).clear(); } public boolean add(Object o) { return ((MyUpdatableCollection) c).add(o); } public boolean remove(Object o) { return ((MyUpdatableCollection) c).remove(o); } public boolean isEmpty() { return c.isEmpty(); } public int size() { return c.size(); } public Iterator iterator() { return ((MyIterableCollection) c).iterator(); } } public class _Updatable implements MyUpdatableCollection { MyCollection c; public _Updatable(MyCollection c) { this.c = c; } public void clear() { ((MyUpdatableCollection) c).clear(); } public boolean add(Object o) { return ((MyUpdatableCollection) c).add(o); } public boolean remove(Object o) { return ((MyUpdatableCollection) c).remove(o); } public boolean isEmpty() { return c.isEmpty(); } public int size() { return c.size(); } } public class _Iterable implements MyIterableCollection { MyCollection c; public _Iterable(MyCollection c) { this.c = c; } public boolean isEmpty() { return c.isEmpty(); } public int size() { return c.size(); } public Iterator iterator() { return ((MyIterableCollection) c).iterator(); } } public class _None implements MyCollection { MyCollection c; public _None(MyCollection c) { this.c = c; } public boolean isEmpty() { return c.isEmpty(); } public int size() { return c.size(); } } |
Het probleem is dat ik nu telkens het type van de inputcollectie moet controleren, om een collectie van hetzelfde type aan te kunnen maken. Dit is niet handig, en zeker niet praktisch bij een groter aantal interfaces. Het aantal combinaties is exponentieel!
Mijn vraag is nu: kan dit beter? Ik zit er al een tijdje naar te staren, maar ik denk dat ik hier op 1 van de beperkingen van Java stuit.