C++ 工厂方法实施-C++;

C++ 工厂方法实施-C++;,c++,templates,design-patterns,factory,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: vir

我有以下用于“工厂”设计模式实现的代码

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);
}
类笔{
公众:
虚空绘制()=0;
};
类红笔:公共笔{
公众:
虚空绘制(){

cout在您发布的示例中,工厂或模板方法对我来说都没有意义。 我的解决方案涉及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;
}
类笔{
公众:
Pen():m_颜色(0,0,0,0)/*默认颜色为黑色*/
{            
}
笔(常量颜色和c):m_颜色(c)
{
}
笔(常量笔和其他):m_颜色(其他.color())
{
}
虚空绘制()
{

cout作为我另一个答案的补充,仅讨论工厂模式与模板使用:

使用模板的主要(也是最简单的)原因是,除了它所处理的数据类型之外,您的代码在任何情况下都是相同的。 可以编写工厂函数createVector(“string”),并手动键入每个容器——但这显然是次优的

即使代码不同,不仅数据类型不同,也可以使用模板专门化——但在许多情况下,工厂函数更有意义

作为一个例子,考虑一个数据库抽象库。使用模板特化是可能的,这样库可以像“db::驱动程序”那样使用。但是这会迫使您在代码中到处键入数据库类型(使图书馆在开始时有点无用……),或对接口类型db::driver类执行案例


在本例中,更直观的做法是说db::get_driver(odbc)并将适当的类转换回接口类型。

您的工厂很好。我认为,
BluePen
等只是示例类名称。如果满足以下条件,您可以使用模板:

当您在编译时(即编写代码时)知道需要返回特定类型时,请使用模板。否则,您不能

这意味着在代码中,您可以这样做:

template<typename PenType>
auto_ptr<Pen> createPen(){
    return auto_ptr<Pen>(new PenType);
}
模板
auto_ptr createPen(){
返回自动_ptr(新的戊型);
}
有了它,你就可以像这样使用它了

...
auto_ptr<Pen> p = createPen<BluePen>();
...
。。。
auto_ptr p=createPen();
...

<> P>但是,模板参数, BuelpEn>代码>不能是运行时设置为类型的变量。在示例中,您传递一个字符串,当然可以在运行时设置它。因此,当您读取时可以使用C++模板,那么该建议仅是条件正确的。y在编译时完成。如果该条件合适,则模板解决方案是正确的选择。它在运行时不会花费任何费用,并且正是您所需要的。

通过为颜色声明特殊的空类,您可以使用模板完成所有操作。这要求在编译时提供所有颜色选择。通过这样,就避免了将基类与虚拟方法一起使用

struct Red{};
struct Blue{};

template < typename Color >
class Pen{};

template <>
class Pen< Red >
{
     void Draw(){
         cout << "Drawing with red pen" << endl;
     }
};

template <>
class Pen< Blue >
{
     void Draw(){
         cout << "Drawing with blue pen" << endl;
     }
};

template < typename Color >
std::auto_ptr< Pen< Color > > createPen()
{
     return auto_ptr< Pen< Color > >(new Pen< Color >());
}
struct Red{};
结构蓝{};
模板
类Pen{};
模板
类笔<红色>
{
作废提款(){
coutcreatepen()
{
返回auto_ptr>(新笔());
}

另一种方法是将创建者函数动态注册到动态工厂对象

BluePen *create_BluePen() { return new BluePen; }
static bool BluePen_creator_registered = 
                       Factory::instance()->registerCreator("BluePen", 
                                                            create_BluePen);
这样做的一个有趣效果是,静态bool变量
BluePen creator registered
将在
main()
开始之前设置,从而使注册自动化

这些行有时是通过普通宏生成的,例如

#define METAIMPL( _name ) \
_name *create_ ## _name() { return new _name; } \
static bool _name ## _creator_registered = \
                        Factory::instance()->registerCreator(# _name, \
                                                             create_ ## _name)
…并在构造函数附近使用

METAIMPL( BluePen ); // auto registers to the Factory

BluePen::BluePen() : Pen() {
   // something
}
然后,工厂的任务将是存储和查找这些创建者函数

如果您想了解更多信息,请参阅第4.1章“元信息”下的内容,其中还包括扩展的方法,以包括inspector功能的可能性

我从使用这一点中得知,这是一个将旧MaApp移植到C++和X11的项目。Eric Gamma等人开始考虑设计模式


并且…(2011年5月7日)终于开始向github推出一个示例

您可以编写一个通用对象工厂类作为模板类(或者使用本文中很好地描述的一个)


这样,如果您的代码中有多个工厂,那么定义每个工厂的工作量就更少了。

关于这个答案,我有一个单独的SO问题:您有没有机会看一看?提前谢谢。在您的代码中,引用复制构造函数有什么意义?它被称为复制构造函数,将在sur被调用翻页时间。在编写代码时,除了说当我复制一支笔时,我要做的是复制笔的颜色外,没有什么重要的意义。如果
颜色
更复杂,这可能会更重要。