KoreanFoodie's Study
디자인 패턴 (GOF) #5 - Dependency Injection Principle (의존성 역전 원리) 본문
Game Dev/Design Patterns
디자인 패턴 (GOF) #5 - Dependency Injection Principle (의존성 역전 원리)
GoldGiver 2022. 6. 8. 10:48
GoF 의 디자인 패턴과 강의를 참고하여 디자인 패턴에 대한 내용을 정리하고 있습니다.
Dependency Injection Principle (의존성 역전 원리)
부모 - 자식 관계를 설정하는 Relationship 클래스와 관계를 검색하는 Research 클래스가 있다고 가정해보자. 다음과 같이 코드를 짠다면 어떨까?
#include <iostream>
#include <string>
#include <vector>
#include <tuple>
using namespace std;
// 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.
enum class Relationship
{
parent,
child,
sibling
};
struct Person
{
string name;
};
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 });
relations.push_back({ child, Relationship::child, parent });
}
};
struct Research // high-level
{
Research(const Relationships& relationships)
{
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 << 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);
return 0;
}
위의 코드에서, Research 는 high-level 임에도 불구하고, 구현을 보면 RelationShips 클래스의 내부 구조에 직접적으로 의존하고 있음을 알 수 있다.
이를 해결하고, high-level 에서는 abstraction 이 detail 에 의존하지 않도록 refactoring 을 하면 다음과 같이 고칠 수 있다.
struct RelationshipBrowser
{
virtual vector<Person> find_all_children_of(const string& name) = 0;
};
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});
}
vector<Person> find_all_children_of(const string &name) override
{
vector<Person> result;
for (auto&& [first, rel, second] : relations)
{
if (first.name == name && rel == Relationship::parent)
{
result.push_back(second);
}
}
return result;
}
};
struct Research // high-level
{
Research(RelationshipBrowser& browser)
{
for (auto& child : browser.find_all_children_of("John"))
{
cout << "John has a child called " << child.name << endl;
}
}
};
Relationships 내부에 정의된 find_all_children_of 함수를 사용함으로써 Research 라는 high-level 클래스가 더는 Relationships 라는 low-level 모델에 의존하지 않게 되었다!
'Game Dev > Design Patterns' 카테고리의 다른 글
디자인 패턴 (GOF) #4 - Interface Segregation Principle (인터페이스 분리 원칙) (0) | 2022.06.08 |
---|---|
디자인 패턴 (GOF) #3 - Liskov Substitution Principle (리스코프 치환 원칙) (0) | 2022.06.07 |
디자인 패턴 (GOF) #2 - Open-Closed Principle (개방-폐쇄 원칙) (0) | 2022.06.07 |
디자인 패턴 (GOF) #1 - Single Responsibility Principle (단일 책임 원칙) (0) | 2022.06.07 |
Comments