-
Notifications
You must be signed in to change notification settings - Fork 1
/
dependency_inversion_principle.cpp
117 lines (104 loc) · 2.9 KB
/
dependency_inversion_principle.cpp
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
116
117
/***
Acknowledagement: This is a lecture note for course https://www.udemy.com/course/patterns-cplusplus/ by
@Dmitri Nesteruk
Title: Dependency Inversion Principle
// 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.
Shiyu Mou
***/
#include <iostream>
#include <string>
#include <vector>
#include <tuple>
using namespace std;
enum class Relationship
{
parent,
child,
sibling
};
struct Person
{
string name;
};
/*** A bad idea that breaks dependency inversion principle***/
// low level module
struct Relationships // low level
{
vector<tuple<Person, Relationship, Person>> relations;
void add_parent_and_child(const Person& parent, const Person& child){
relations.push_back({parent, Relationship::parent, child});
realtions.push_back({child, Relationship::child, parent});
}
};
// high level research module
struct Research
{
Research(Relationships& relationships) // depend on low level
{
// depend on the low level details
// bad if the low level code decides to change
// the container of relations (map) or make it private
// then the high level code breaks
auto& relations = relationships.relations;
for (auto&& [first, rel, second] : relations)
{
if (first.name == "John" && rel == Relationship::parent)
{
cout << "John has a child called "<< second.name;
}
}
}
};
/*** A better idea that breaks dependency inversion principle***/
// now introduce an abstraction
struct RelationshipBrowser
{
virtual vector<Person> find_all_children_of(const string& name) = 0;
};
// low level
struct Relationships : RelationshipBrowser // low level
{
vector<tuple<Person, Relationship, Person>> relations;
void add_parent_and_child(const Person& parent, const Person& child){
relations.push_back({parent, Relationship::parent, child});
relations.push_back({child, Relationship::child, parent});
}
// move f
vector<Person> find_all_children_of(const string& name) override
{
vector<Person> result;
for (auto&& [first, rel, second]: relations)
{
if (first.name == name && rel == Relationships::parent)
{
result.push_back(second);
}
}
return result;
}
};
// high level
struct Research
{
// won't depend on details, now depends on abstraction, thanks to polymorphsim,
// you can pass subclass object here
Research(RelationshipBrowser& browser)
{
for (auto& child : browser.find_all_children_of("John"))
{
cout << "John has a child called " << child.name << endl;
}
}
};
int main(){
Person parent{"John"};
Person child1{"Chris"};
Person child2{"Matt"};
Relationships relationships;
relationships.add_parent_and_child(parent, child1);
relationships.add_parent_and_child(parent, child2);
Research _(relationships);
}