/ 디자인 패턴들 / 플라이웨이트 / C++ C++로 작성된 플라이웨이트 플라이웨이트는 구조 패턴이며 프로그램들이 객체들의 메모리 소비를 낮게 유지하여 방대한 양의 객체들을 지원할 수 있도록 합니다. 이 패턴은 여러 객체 사이의 객체 상태를 공유하여 위를 달성합니다. 다르게 설명하자면 플라이웨이트는 다른 객체들이 공통으로 사용하는 데이터를 캐싱하여 RAM을 절약합니다. 플라이웨이트에 대하여 더 자세히 알아보세요 내비게이션 소개 개념적인 예시 main Output 복잡도: 인기도: 사용 사례들: 플라이웨이트 패턴의 유일한 목적은 메모리 섭취를 최소화하는 것입니다. 당신의 프로그램이 RAM 부족으로 문제를 겪지 않는다면 당분간 이 패턴을 무시할 수 있습니다. 식별: 플라이웨이트는 새로운 객체들 대신 캐싱 된 객체들을 반환하는 생성 메서드의 유무로 식별될 수 있습니다. 개념적인 예시 이 예시는 플라이웨이트의 구조를 보여주고 다음 질문에 중점을 둡니다: 패턴은 어떤 클래스들로 구성되어 있나요? 이 클래스들은 어떤 역할을 하나요? 패턴의 요소들은 어떻게 서로 연관되어 있나요? main.cc: 개념적인 예시 /** * Flyweight Design Pattern * * Intent: Lets you fit more objects into the available amount of RAM by sharing * common parts of state between multiple objects, instead of keeping all of the * data in each object. */ struct SharedState { std::string brand_; std::string model_; std::string color_; SharedState(const std::string &brand, const std::string &model, const std::string &color) : brand_(brand), model_(model), color_(color) { } friend std::ostream &operator<<(std::ostream &os, const SharedState &ss) { return os << "[ " << ss.brand_ << " , " << ss.model_ << " , " << ss.color_ << " ]"; } }; struct UniqueState { std::string owner_; std::string plates_; UniqueState(const std::string &owner, const std::string &plates) : owner_(owner), plates_(plates) { } friend std::ostream &operator<<(std::ostream &os, const UniqueState &us) { return os << "[ " << us.owner_ << " , " << us.plates_ << " ]"; } }; /** * The Flyweight stores a common portion of the state (also called intrinsic * state) that belongs to multiple real business entities. The Flyweight accepts * the rest of the state (extrinsic state, unique for each entity) via its * method parameters. */ class Flyweight { private: SharedState *shared_state_; public: Flyweight(const SharedState *shared_state) : shared_state_(new SharedState(*shared_state)) { } Flyweight(const Flyweight &other) : shared_state_(new SharedState(*other.shared_state_)) { } ~Flyweight() { delete shared_state_; } SharedState *shared_state() const { return shared_state_; } void Operation(const UniqueState &unique_state) const { std::cout << "Flyweight: Displaying shared (" << *shared_state_ << ") and unique (" << unique_state << ") state.\n"; } }; /** * The Flyweight Factory creates and manages the Flyweight objects. It ensures * that flyweights are shared correctly. When the client requests a flyweight, * the factory either returns an existing instance or creates a new one, if it * doesn't exist yet. */ class FlyweightFactory { /** * @var Flyweight[] */ private: std::unordered_map<std::string, Flyweight> flyweights_; /** * Returns a Flyweight's string hash for a given state. */ std::string GetKey(const SharedState &ss) const { return ss.brand_ + "_" + ss.model_ + "_" + ss.color_; } public: FlyweightFactory(std::initializer_list<SharedState> share_states) { for (const SharedState &ss : share_states) { this->flyweights_.insert(std::make_pair<std::string, Flyweight>(this->GetKey(ss), Flyweight(&ss))); } } /** * Returns an existing Flyweight with a given state or creates a new one. */ Flyweight GetFlyweight(const SharedState &shared_state) { std::string key = this->GetKey(shared_state); if (this->flyweights_.find(key) == this->flyweights_.end()) { std::cout << "FlyweightFactory: Can't find a flyweight, creating new one.\n"; this->flyweights_.insert(std::make_pair(key, Flyweight(&shared_state))); } else { std::cout << "FlyweightFactory: Reusing existing flyweight.\n"; } return this->flyweights_.at(key); } void ListFlyweights() const { size_t count = this->flyweights_.size(); std::cout << "\nFlyweightFactory: I have " << count << " flyweights:\n"; for (std::pair<std::string, Flyweight> pair : this->flyweights_) { std::cout << pair.first << "\n"; } } }; // ... void AddCarToPoliceDatabase( FlyweightFactory &ff, const std::string &plates, const std::string &owner, const std::string &brand, const std::string &model, const std::string &color) { std::cout << "\nClient: Adding a car to database.\n"; const Flyweight &flyweight = ff.GetFlyweight({brand, model, color}); // The client code either stores or calculates extrinsic state and passes it // to the flyweight's methods. flyweight.Operation({owner, plates}); } /** * The client code usually creates a bunch of pre-populated flyweights in the * initialization stage of the application. */ int main() { FlyweightFactory *factory = new FlyweightFactory({{"Chevrolet", "Camaro2018", "pink"}, {"Mercedes Benz", "C300", "black"}, {"Mercedes Benz", "C500", "red"}, {"BMW", "M5", "red"}, {"BMW", "X6", "white"}}); factory->ListFlyweights(); AddCarToPoliceDatabase(*factory, "CL234IR", "James Doe", "BMW", "M5", "red"); AddCarToPoliceDatabase(*factory, "CL234IR", "James Doe", "BMW", "X1", "red"); factory->ListFlyweights(); delete factory; return 0; } Output.txt: 실행 결과 FlyweightFactory: I have 5 flyweights: BMW_X6_white Mercedes Benz_C500_red Mercedes Benz_C300_black BMW_M5_red Chevrolet_Camaro2018_pink Client: Adding a car to database. FlyweightFactory: Reusing existing flyweight. Flyweight: Displaying shared ([ BMW , M5 , red ]) and unique ([ CL234IR , James Doe ]) state. Client: Adding a car to database. FlyweightFactory: Can't find a flyweight, creating new one. Flyweight: Displaying shared ([ BMW , X1 , red ]) and unique ([ CL234IR , James Doe ]) state. FlyweightFactory: I have 6 flyweights: BMW_X1_red Mercedes Benz_C300_black BMW_X6_white Mercedes Benz_C500_red BMW_M5_red Chevrolet_Camaro2018_pink