-----------------------------------------------------------------------------
[Flyweight]
의도:
대규모의 미세한 객체들을 효과적으로 사용하기 위해서는 공유 개념을 도입
-----------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
//
// A Structural part of GoF's Design Patterns
//
// - Flyweight
//
/////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <tchar.h>
#include <iostream>
#include <memory>
#include <map>
#include <string>
#include <list>
#include <algorithm>
/////////////////////////////////////////////////////////////////////////////
//
// Flyweight
//
/////////////////////////////////////////////////////////////////////////////
class Flyweight
{
public:
virtual ~Flyweight() {}
public:
virtual void Operation (void) = 0;
};
class ConcreteFlyweight : public Flyweight
{
public:
ConcreteFlyweight (std::string s, int n) :
Key_ (n),
Value_ (s)
{
}
public:
virtual void Operation (void)
{
std::cout << Value_.c_str() << "(" << Key_ << ")" << std::endl;
}
private:
int Key_;
std::string Value_;
};
class UnsharedConcreteFlyweight : public Flyweight
{
public:
UnsharedConcreteFlyweight (std::string s) :
Value_ (s)
{
}
public:
virtual void Operation (void)
{
std::cout << Value_.c_str() << std::endl;
}
private:
std::string Value_;
};
//// ------------------------------------------------------------------------
class FlyweightFactory
{
private:
struct PoolDeleter
{
public:
PoolDeleter() : Count_(0) {}
public:
void operator()(std::pair<int,Flyweight*> i)
{
Flyweight *p = i.second;
if (p)
{
Count_++;
delete p;
}
}
operator int ()
{
return Count_;
}
private:
int Count_;
};
public:
virtual ~FlyweightFactory ()
{
int Count;
Count = std::for_each(Pool_.begin(), Pool_.end(), PoolDeleter());
std::cout << "~FlyweightFactory(): [ConcreteFlyweight] deleting count="
<< Count
<< std::endl
<< std::endl;
}
public:
Flyweight* GetFlyweight (std::string value, int key)
{
Flyweight* f;
if ( Pool_.end() == Pool_.find (key) )
{
f = new ConcreteFlyweight (value, key);
Pool_[key] = f;
}
else
{
f = Pool_[key];
}
return f;
}
Flyweight* GetUnsharedFlyweight (std::string value)
{
Flyweight* f;
f = new UnsharedConcreteFlyweight ( value );
return f;
}
private:
std::map <int,Flyweight*> Pool_;
};
//// ------------------------------------------------------------------------
class Context
{
private:
template<class T>
struct OperationCaller : public std::unary_function<T, void>
{
public:
void operator()(T ptr)
{
if (ptr)
ptr->Operation();
}
};
template<class T>
struct ListDeleter : public std::unary_function<T, void>
{
public:
ListDeleter() : Count_(0) {}
public:
void operator()(T ptr)
{
if (ptr)
{
if (dynamic_cast<UnsharedConcreteFlyweight*>(ptr))
{
Count_++;
delete ptr;
}
}
}
operator int ()
{
return Count_;
}
private:
int Count_;
};
public:
~Context ()
{
int Count;
Count = std::for_each(List_.begin(), List_.end(), ListDeleter<Flyweight*>());
std::cout << "~Context(): [UnsharedConcreteFlyweight] deleting count="
<< Count
<< std::endl;
}
public:
void Add (std::string s, int n=0)
{
if (n)
List_.push_back ( Factory_.GetFlyweight (s, n) );
else
List_.push_back ( Factory_.GetUnsharedFlyweight (s) );
}
void Operation (void)
{
std::for_each(List_.begin(), List_.end(), OperationCaller<Flyweight*>());
std::cout << std::endl;
}
private:
std::list<Flyweight*> List_;
FlyweightFactory Factory_;
};
/////////////////////////////////////////////////////////////////////////////
//
// Startup
//
/////////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
Context context;
context.Add ("one", 1);
context.Add ("two" );
context.Add ("one", 1);
context.Add ("two" );
context.Add ("one", 1);
context.Add ("two" );
context.Add ("one", 1);
context.Add ("two" );
context.Add ("one", 1);
context.Add ("two" );
context.Operation ();
return 0;
}
one(1)
two
one(1)
two
one(1)
two
one(1)
two
one(1)
two
~Context(): [UnsharedConcreteFlyweight] deleting count=5
~FlyweightFactory(): [ConcreteFlyweight] deleting count=1