#include <iostream>
#include <string>
#include <unordered_map>
// 공유한 상태
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_ << " ]";
}
};
// shared_state를 공통의 부분으로 저장하고 나머지 상태는 메소드를 통해 accept
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";
}
};
// FlyweightFactoy는 Flyweight 객체를 생성 및 관리
class FlyweightFactory
{
/**
* @var Flyweight[]
*/
private:
std::unordered_map<std::string, Flyweight> flyweights_;
// Flyweight의 shared state에서 가지는 string 해쉬를 리턴
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)));
}
}
// shared_state key를 가지고 기존의 Flyweight가 있으면 return 없으면 새로 객체를 만들고 map에 저장
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);
}
// 현재 map에 가지고 있는 Flyweights를 출력
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});
// 클라이언트 코드는 상태를 저장하거나 계산하여 Flyweight 메소드에 전달
flyweight.Operation({owner, plates});
}
int main()
{
// Client code
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;
std::cout << "Check!!";
return 0;
}
댓글남기기