2014-11-25 15 views
1

我在学习设计模式。我是一名C++程序员。目前,我正在玩弄原型模式。我可以将Prototype与工厂类型联系起来。但是,工厂和原型模式之间存在很多差异。例如,在原型模式中,每个派生类都将其原型与基类/超类一起注册。为什么他们说在Proto-type Pattern中 - 只要需要新的对象就可以复制原始对象?

但是,看着wikipedia article - 我无法理解以下几点。

  1. 而不是检索数据和每次创建一个新对象时重新解析它,原型图案可以用来简单地重复每当需要一个新的原始对象。

  2. 避免以标准方式创建新对象(例如,使用'new'关键字)对于给定应用程序过于昂贵的内在成本。

这是我创建的程序,用于演示C++中的原型模式。但是,我无法从中找到任何好处。原型模式如何帮助快速创建对象。我可以看到对象每次都必须调用“新”。这是整个程序,如果你认为我没有正确实现原型模式,请纠正我。

对不起,长期的计划 - 但相信我,这很简单。

就像一个工厂对象 - 这里是原型类

-- basically an abstract. 

class Itransport 
{ 

public: 

enum transportPacketType 
{ 
    udp, 
    tcp, 
    MAX 
}; 

private: 
    static std::list<Itransport *> prototypesList; 

protected: 
    virtual Itransport::transportPacketType getPacketType() = 0; 
    virtual Itransport* clone() = 0; 

    /** This will be called by the derived classes **/ 
    static void registertoPrototypeList(Itransport *packet) 
    { 
     prototypesList.push_back(packet); 
    } 
public: 

    virtual void showMessage() = 0; 

static Itransport* makeClone(Itransport::transportPacketType packType) 
    { 
     std::list<Itransport *>::iterator it; 

     for(it = prototypesList.begin(); it != prototypesList.end(); it++) 
      { 
       if((*it)->getPacketType() == packType) 
       { 
        return (*it)->clone(); 
       } 
      } 
    } 

    virtual ~Itransport() = 0; 
}; 

Itransport::~Itransport() 
{ 
    std::cout<<"Itransport Destructor called"<<std::endl; 
} 

std::list<Itransport *> Itransport::prototypesList; 

这里是Itransport包的具体类型 -

class udpPacket: public Itransport 
{ 

private: 

    static udpPacket udpTransportPacket; 

protected: 
Itransport::transportPacketType getPacketType() 
{ 
    return Itransport::udp; 
} 

Itransport* clone() 
     { 
      return new udpPacket(); 
     } 

public: 

void showMessage() 
{ 
    std::cout<<"This is a UDP Packet"<<std::endl; 
} 

udpPacket() 
{ 
    std::cout<<"UDP Packet Constructed"<<std::endl; 
    registertoPrototypeList(this); 
} 

~udpPacket() 
{ 
    std::cout<<"Destructor of udp called"<<std::endl; 
} 

}; 

static udpPacket udpTransportPacket; 

这里是客户端 -

int main() 
{ 
    Itransport *udpPacket; 
    Itransport *udpPacket2; 
    udpPacket = Itransport::makeClone(Itransport::udp); 
    udpPacket->showMessage(); 

    udpPacket2 = Itransport::makeClone(Itransport::udp); 
    udpPacket2->showMessage(); 

    delete udpPacket; 
    delete udpPacket2; 

    return 0; 
} 

我在这里找不到与'新'有关的任何好处。请点亮它。

+0

而不是'return new udpPacket();'它应该是'return new udpPacket(* this);'因为你想创建一个原型的副本。 – 2014-11-25 21:50:26

回答

2

我可以在说明第一点有一个去:

而不是检索数据,并且每个创建一个新的 对象时间重新解析它,原型图案可以用来简单地 重复每当需要新的对象时,原始对象。

想象一下,必须制造大量怪物的电脑游戏。说各种不同类型的怪物在编译的时候不知道,但你构建从一些输入数据,提供有关的怪物是什么颜色信息的特定类型等的怪物:每次你想

class Monster { 
public: 
    Monster(InputDataHandle handle) { 
    // Retrieve input data... 
    // Parse input data... 
    } 
    void setPosition(Position); 
}; 

然后要建造一个红色的怪物,你必须检索数据并重新解析:

// Spawn a lot of red monsters 
for (int i = 0; i != large_number; ++i) { 
    auto red = new Monster(red_monster_data); // Must retrieve data and re-parse! 
    red->setPosition(getRandomPosition()); 
    game.add(red); 
} 

很明显,这是低效的。解决它的一种方法是使用原型模式。您可以创建一个“原型”红色怪物,你要创建一个红色的怪物,你只需复制原型的一个实例每次和你没有来检索和重新解析输入数据:

auto prototype_red_monster = new Monster(red_monster_data); 

for (int i = 0; i != large_number; ++i) { 
    auto red = prototype_red_monster->clone(); 
    red->setPosition(getRandomPosition()); 
    game.add(red); 
} 

但克隆功能如何实施?这给我们带来了第二点,我真的不明白:

避免以标准方式 创建一个新的对象(例如,使用new关键字)所固有的成本时,它是昂贵对于 给定的应用程序。

克隆功能从根本上必须为新对象分配内存并从其自身拷贝数据。当我们谈论“new关键字的固有成本”时,我不确定我知道他们指的是什么。这些示例分别是具有clone()MemberwiseClone()的Java和C#。在这些语言中,您不需要拨打new。我不知道clone()MemberwiseClone()是如何实现的,但我不明白他们如何“避免new关键字的固有成本”。

在C++中,我们必须实现clone()自己和它通常会使用new和使用拷贝构造函数:

Monster* clone() { 
    return new Monster(*this); 
} 

在这种情况下,拷贝构造函数是不是从头创建对象便宜得多。在你的情况下,它可能不是。

你不能找到你的情况原型模式任何好处可能意味着它是你的情况下,错误的花样,你会用像Object PoolFlyweightAbstract Factory模式不同的模式更好的事实。

+0

我喜欢你的答案,但它清楚地表明,在C++中没有原型模式的好处。 Java中的clone()方法与新运算符不同。 – 2014-11-26 05:34:20

+0

我不同意在C++中没有原型模式的好处。很明显,我提供的例子有好处。还有很多其他情况下,它是有用的。你的情况可能没有用处。 – 2014-11-26 06:20:12

相关问题