Nav*_*K N 3 c++ templates design-patterns factory
我有"工厂"设计模式实现的以下代码.
class Pen{
public:
virtual void Draw() = 0;
};
class RedPen : public Pen{
public:
virtual void Draw(){
cout << "Drawing with red pen" << endl;
}
};
class BluePen : public Pen{
public:
virtual void Draw(){
cout << "Drawing with blue pen" << endl;
}
};
auto_ptr<Pen> createPen(const std::string color){
if(color == "red")
return auto_ptr<Pen>(new RedPen);
else if(color == "blue")
return auto_ptr<Pen>(new BluePen);
}
Run Code Online (Sandbox Code Playgroud)
但我听说可以使用"C++模板"以更好的方式完成.任何人都可以帮助它如何完成以及模板方法如何比这更好?
有什么想法吗
epa*_*tel 12
另一种方法是将创建者函数动态注册到动态Factory对象.
BluePen *create_BluePen() { return new BluePen; }
static bool BluePen_creator_registered =
Factory::instance()->registerCreator("BluePen",
create_BluePen);
Run Code Online (Sandbox Code Playgroud)
这样做的一个有趣的效果是静态bool变量BluePen-creator-registered将在main()开始之前设置,从而使注册自动化.
这些线有时是通过普通的宏,即as
#define METAIMPL( _name ) \
_name *create_ ## _name() { return new _name; } \
static bool _name ## _creator_registered = \
Factory::instance()->registerCreator(# _name, \
create_ ## _name)
Run Code Online (Sandbox Code Playgroud)
...并且使用接近构造函数
METAIMPL( BluePen ); // auto registers to the Factory
BluePen::BluePen() : Pen() {
// something
}
Run Code Online (Sandbox Code Playgroud)
然后Factory的任务是存储和查找这些创建者函数.我把剩下的作为练习 ;)即使用METADECL宏
如果您想了解更多信息,请参见这里下章4.1元信息还包括一个用于扩展到包括可能的方法检查功能
我从使用ET ++学到了这一点,这是一个将旧MacApp移植到C++和X11的项目.为此,Eric Gamma等开始考虑设计模式
并且...(2011年5月7日)最后来到github
https://github.com/epatel/cpp-factory
在您发布的示例中,工厂或模板方法对我来说都没有意义。我的解决方案涉及 Pen 类中的数据成员。
class Pen {
public:
Pen() : m_color(0,0,0,0) /* the default colour is black */
{
}
Pen(const Color& c) : m_color(c)
{
}
Pen(const Pen& other) : m_color(other.color())
{
}
virtual void Draw()
{
cout << "Drawing with a pen of color " << m_color.hex();
}
void setColor(const Color& c) { m_color = c; }
const Color& color() const { return m_color; }
private:
Color m_color;
};
class Color {
public:
Color(int r, int g, int b, int a = 0) :
m_red(r), m_green(g), m_blue(other.blue()), m_alpha(a)
{
}
Color(const Color& other) :
m_red(other.red()), m_green(other.green()),
m_blue(other.blue()), m_alpha(other.alpha())
{
}
int red() const { return m_red; }
int green() const { return m_green; }
int blue() const { return m_blue; }
int alpha() const { return m_alpha; }
std::string hex() const
{
std::ostringstream os;
char buf[3];
os << "#";
sprintf(buf, "%2X", red());
os << buf;
sprintf(buf, "%2X", green());
os << buf;
sprintf(buf, "%2X", blue());
os << buf;
sprintf(buf, "%2X", alpha());
os << buf;
return os.str();
}
private:
int m_red;
int m_green;
int m_blue;
int m_alpha;
}
Run Code Online (Sandbox Code Playgroud)
当然,颜色类必须根据您使用的绘图 API 进行调整——并且可能比这个更高级(不同的颜色空间等)。
使用模板没有意义的原因是(大概)不同绘图操作之间的唯一区别是颜色变量。因此,通过使用模板(或像您一样手动声明不同的类),您将复制类似的代码。这将使您的程序变大并减慢速度。
因此,绘制函数应该将颜色作为参数,或者(如我的示例中)将颜色作为类数据成员。
你的工厂很好.我接受它BluePen等等只是示例类名.如果满足以下条件,您可以使用模板:
当您在编译时(即编写代码时)知道要返回特定类型时,请使用模板.否则,你不能.
这意味着在代码中,您可以这样做:
template<typename PenType>
auto_ptr<Pen> createPen(){
return auto_ptr<Pen>(new PenType);
}
Run Code Online (Sandbox Code Playgroud)
有了这些,你可以使用它
...
auto_ptr<Pen> p = createPen<BluePen>();
...
Run Code Online (Sandbox Code Playgroud)
但是,该模板参数BluePen不能是在运行时设置为类型的变量.在您的示例中,您传递一个字符串,当然可以在运行时设置.因此,当您读到可以使用C++模板时,那么该建议只有条件成立 - 那么,当您决定创建哪支笔时,已经在编译时完成了.如果条件符合,那么模板解决方案是在做正确的事情.它不会在运行时花费任何成本,而且正是您所需要的.