-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathDIP.java
More file actions
98 lines (79 loc) · 3.1 KB
/
Copy pathDIP.java
File metadata and controls
98 lines (79 loc) · 3.1 KB
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
// Dependency Inversion Principle - family tree application as the example
// A. High-level modules should not depend on low-level modules.
// Both should depend on abstractions.
// B. Abstractions should not depend on details.
// Details should depend on abstractions.
package solidprinciples.dip;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.*;
import java.util.stream.Collectors;
import org.javatuples.Triplet;
enum Relationship {
PARENT,
CHILD,
SIBLING
}
class Person {
public String name;
//dob, nationality, etc in a real app
public Person(String name) {
this.name = name;
}
}
// abstraction here to implement on low-level module
interface RelationshipBrowser {
List<Person> findAllChildrenOf(String name);
}
class Relationships implements RelationshipBrowser // low-level module, it's related to data storage/keeping a list. No business logic.
{
private List<Triplet<Person, Relationship, Person>> relations = new ArrayList<>();
/* Problem: we are exposing an internal storage implementation of relations
(the private variable above) as a public getter for everyone to access */
public List<Triplet<Person, Relationship, Person>> getRelations() {
return relations;
}
public void addParentAndChild(Person parent, Person child) {
relations.add(new Triplet<>(parent, Relationship.PARENT, child));
relations.add(new Triplet<>(child, Relationship.CHILD, parent));
}
@Override
public List<Person> findAllChildrenOf(String name) {
return relations.stream()
.filter(x -> Objects.equals(x.getValue0().name, name)
&& x.getValue1() == Relationship.PARENT)
.map(Triplet::getValue2)
.collect(Collectors.toList());
}
}
class Research // high-level module, allows us to perform operations on lower-level constructs
{
/* Violating DIP: constructor of high-level module taking low-level
module as a dependency */
// public Research(Relationships relationships) {
// List<Triplet<Person, Relationship, Person>> relations = relationships.getRelations();
// relations.stream()
// .filter(x -> x.getValue0().name.equals("John")
// && x.getValue1() == Relationship.PARENT)
// .forEach(ch -> System.out.println (
// "John has a child called " + ch.getValue2().name
// ));
// }
//Correct implementation uses abstract interface
public Research(RelationshipBrowser browser) {
List<Person> children = browser.findAllChildrenOf("John");
for (Person child : children)
System.out.println(("John has a child called " + child.name));
}
}
class DIPDemo {
public static void main(String[] args) {
Person parent = new Person("John");
Person child1 = new Person("Chris");
Person child2 = new Person("Matt");
Relationships relationships = new Relationships();
relationships.addParentAndChild(parent, child1);
relationships.addParentAndChild(parent, child2);
new Research(relationships);
}
}