享元模式和 C++模板
我有蝇量级模式。我有抽象类 Glyph。我有类 Letter 和从 Glyph 派生的抽象代码。我有从 Code 派生的 YusciiCode、UniCyrCode 和 UniLatCode。
我的享元工厂可以这样完成:
template <class T>
class CodeFactory : public AbstractCodeFactory
{
public:
CodeFactory();
virtual ~CodeFactory();
virtual Glyph* GetFlyweight(unsigned int code);
virtual Glyph* GetFlyweight(string letter);
private:
// pool of flyweights (codes or letters)
map <unsigned int, Glyph*> my_code_map;
map <string, Glyph*> my_letter_map;
};
可以这样完成:
template <class key, class T>
class CodeFactory : public AbstractCodeFactory
{
public:
CodeFactory();
virtual ~CodeFactory();
virtual Glyph* GetFlyweight(key code);
private:
// pool of flyweights (codes or letters)
map <key, Glyph*> my_code_map;
};
在第一个示例中,GCC 链接器告诉我没有 Letter(unsigned int) 和 xxxCode(string) 构造函数。事实上,没有任何构造函数,GCC 是对的,但是有没有比定义这些构造函数更好的方法呢?
行上有一个错误
map <key, Glyph*>::iterator it;
在第二个例子中,GCC 编译器告诉我函数 GetFlyweight 的
。这种享元模式的实现方式是什么?
我需要使用它。 这是我当前的实现:
class AbstractCodeFactory
{
public:
AbstractCodeFactory();
virtual ~AbstractCodeFactory();
virtual Glyph* GetFlyweight(unsigned int code) = 0;
virtual Glyph* GetFlyweight(string letter) = 0;
};
template <class T>
class CodeFactory : public AbstractCodeFactory
{
public:
CodeFactory();
virtual ~CodeFactory();
virtual Glyph* GetFlyweight(unsigned int code);
virtual Glyph* GetFlyweight(string letter);
private:
// pool of flyweights (codes or letters)
map <unsigned int, Glyph*> my_code_map;
map <string, Glyph*> my_letter_map;
};
template <class T>
CodeFactory<T>::CodeFactory()
{
// TODO Auto-generated constructor stub
}
template <class T>
CodeFactory<T>::~CodeFactory()
{
// TODO Auto-generated destructor stub
map <unsigned int, Glyph*>::iterator it;
map <string, Glyph*>::iterator l_it;
for (it = my_code_map.begin(); it != my_code_map.end(); ++it)
{
delete it->second;
it->second = NULL;
my_code_map.erase(it);
}
for (l_it = my_letter_map.begin(); l_it != my_letter_map.end(); ++l_it)
{
delete l_it->second;
l_it->second = NULL;
my_letter_map.erase(l_it);
}
}
template <class T>
Glyph* CodeFactory<T>::GetFlyweight(unsigned int code)
{
map <unsigned int, Glyph*>::iterator it;
T *code_class = NULL;
if ((it = my_code_map.find(code)) == my_code_map.end())
{
my_code_map.insert(pair <unsigned int, Glyph*> (code, code_class = new T(code)));
return code_class;
}
else return it->second;
}
template <class T>
Glyph* CodeFactory<T>::GetFlyweight(string letter)
{
map <string, Glyph*>::iterator it;
T *letter_class = NULL;
if ((it = my_letter_map.find(letter)) == my_letter_map.end())
{
my_letter_map.insert(pair <string, Glyph*> (letter, letter_class = new T(letter)));
return letter_class;
}
else return it->second;
}
I have flyweight pattern. I have abstract class Glyph. I have class Letter and abstract Code derived from Glyph. I have YusciiCode, UniCyrCode and UniLatCode derived from Code.
My flyweight factory can be done like this:
template <class T>
class CodeFactory : public AbstractCodeFactory
{
public:
CodeFactory();
virtual ~CodeFactory();
virtual Glyph* GetFlyweight(unsigned int code);
virtual Glyph* GetFlyweight(string letter);
private:
// pool of flyweights (codes or letters)
map <unsigned int, Glyph*> my_code_map;
map <string, Glyph*> my_letter_map;
};
It can be done like this:
template <class key, class T>
class CodeFactory : public AbstractCodeFactory
{
public:
CodeFactory();
virtual ~CodeFactory();
virtual Glyph* GetFlyweight(key code);
private:
// pool of flyweights (codes or letters)
map <key, Glyph*> my_code_map;
};
In the first example GCC linker tell me that there are no Letter(unsigned int) and xxxCode(string) constructor. In fact there aren't any and GCC is right, but is there a better way to do this than to define those constructors?
In the seccond ecample GCC compiler tells me that there is an error on the line
map <key, Glyph*>::iterator it;
of the function GetFlyweight.
What is the way to implement this flyweight pattern?
I need to use it.
Here is my current implementation:
class AbstractCodeFactory
{
public:
AbstractCodeFactory();
virtual ~AbstractCodeFactory();
virtual Glyph* GetFlyweight(unsigned int code) = 0;
virtual Glyph* GetFlyweight(string letter) = 0;
};
template <class T>
class CodeFactory : public AbstractCodeFactory
{
public:
CodeFactory();
virtual ~CodeFactory();
virtual Glyph* GetFlyweight(unsigned int code);
virtual Glyph* GetFlyweight(string letter);
private:
// pool of flyweights (codes or letters)
map <unsigned int, Glyph*> my_code_map;
map <string, Glyph*> my_letter_map;
};
template <class T>
CodeFactory<T>::CodeFactory()
{
// TODO Auto-generated constructor stub
}
template <class T>
CodeFactory<T>::~CodeFactory()
{
// TODO Auto-generated destructor stub
map <unsigned int, Glyph*>::iterator it;
map <string, Glyph*>::iterator l_it;
for (it = my_code_map.begin(); it != my_code_map.end(); ++it)
{
delete it->second;
it->second = NULL;
my_code_map.erase(it);
}
for (l_it = my_letter_map.begin(); l_it != my_letter_map.end(); ++l_it)
{
delete l_it->second;
l_it->second = NULL;
my_letter_map.erase(l_it);
}
}
template <class T>
Glyph* CodeFactory<T>::GetFlyweight(unsigned int code)
{
map <unsigned int, Glyph*>::iterator it;
T *code_class = NULL;
if ((it = my_code_map.find(code)) == my_code_map.end())
{
my_code_map.insert(pair <unsigned int, Glyph*> (code, code_class = new T(code)));
return code_class;
}
else return it->second;
}
template <class T>
Glyph* CodeFactory<T>::GetFlyweight(string letter)
{
map <string, Glyph*>::iterator it;
T *letter_class = NULL;
if ((it = my_letter_map.find(letter)) == my_letter_map.end())
{
my_letter_map.insert(pair <string, Glyph*> (letter, letter_class = new T(letter)));
return letter_class;
}
else return it->second;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
由于您的享元工厂只能生成 Letter、YusciiCode、UniCyrCode 或 UniLatCode 对象,因此我会选择第二个选项(指示键类型的第二个模板参数。
编译器在声明
map::iterator it;
的缺点是编译器无法确定map::iterator
是否引用类型或其他内容。这是因为它取决于模板参数
key
,并且您可能在成员iterator
为 < em>不是类型。为了帮助编译器,您必须指定您希望
map::iterator
引用类型名:As your flyweight factory can only produce either Letter, YusciiCode, UniCyrCode or UniLatCode objects, I would go with the second option (a second template parameter indicating the key type.
The problem that the compiler has with the declaration
map <key, Glyph*>::iterator it;
is that the compiler can"t be sure ifmap<key, Glyph*>::iterator
refers to a type or something else.This is because it depends on the template parameter
key
, and you might have a specialisation ofmap<>
somewhere where the memberiterator
is not a type.To help the compiler out, you must specify that you expect that
map<ket, Glyph*>::iterator
refers to a typename: