为什么以及如何使用原型设计模式



我正在学习设计模式并尝试自己实现它们。对于大多数设计模式,我可以理解那里的使用和实现,但我对原型模式感到困惑。这是我实现它的方法。

船.h

class IShipPrototype
{
public:
virtual IShipPrototype* clone() = 0;
IShipPrototype(const std::string sName, float w = 10, float h = 10, float s = 10) : shipName{ sName }, width{ w }, height{ h }, speed{ s } {};
IShipPrototype(const IShipPrototype &that)
{
shipName = that.shipName;
width = that.width;
height = that.height;
speed = that.speed;
}
void Print()
{
std::cout << "-----------------------n";
std::cout << "tShip Infotn" <<
"Name:tt" << shipName << "n" <<
"Width:tt" << width << "n" <<
"Height:tt" << height << "n" <<
"Speed:tt" << speed << std::endl;
}
void SetShipName(const std::string &newShipName)    { shipName = newShipName; }
void SetShipHeight(float NewHeight)         { height = NewHeight; }
void SetShipWidth(float NewWidth)           { width = NewWidth; }
void SetShipSpeed(float NewSpeed)           { speed = NewSpeed; }

private:
std::string shipName;
float width = 0, height = 0, speed = 0;
};

class Ship : public IShipPrototype
{
public:
Ship(const std::string& sName, float w, float h, float s) : IShipPrototype(sName, w, h, s) {}
Ship(const Ship &ship) : IShipPrototype(ship) {}

IShipPrototype* clone() override
{
return new Ship(*this);
}
};

class ShipFactory
{
public:
ShipFactory()
{
ships[0] = new Ship("titanic", 12, 43, 47);
ships[1] = new Ship("Black pearl", 15, 73, 24);
ships[2] = new Ship("Man O War", 32, 46, 14);
ships[3] = new Ship("Rose Marry", 24, 53, 52);
}
IShipPrototype* CreateCloneShip(int idx)
{
return ships[idx]->clone();
}
private:
std::map<int, IShipPrototype*> ships;
};

主.cpp

int main()
{
ShipFactory *factory = new ShipFactory();
IShipPrototype* titanicClone = factory->CreateCloneShip(0);
IShipPrototype* blackPearlClone = factory->CreateCloneShip(1);
IShipPrototype* manOwarClone = factory->CreateCloneShip(2);
IShipPrototype* roseMarry = factory->CreateCloneShip(3);
titanicClone->SetShipName("titanicClone");
titanicClone->SetShipHeight(100);
titanicClone->Print();
blackPearlClone->SetShipName("blackPearlClone");
blackPearlClone->SetShipSpeed(10);
blackPearlClone->Print();
manOwarClone->SetShipName("manOwarClone");
manOwarClone->SetShipWidth(40);
manOwarClone->Print();
roseMarry->SetShipName("roseMarry");
roseMarry->SetShipSpeed(130);
roseMarry->Print();
getchar();
return EXIT_SUCCESS;
}

让我感到困惑的部分是克隆函数返回接口的指针,这意味着我无法将克隆存储在不同的飞船对象中,例如。Ship* ship = factory->CreateCloneShip(0);.
我认为这种设计模式背后的想法是创建现有对象的克隆,然后更改它的一些细节。
是我的实现不正确还是我错过了什么?

原型模式允许我们通过调用虚拟成员函数(通常在代码中称为clone(),(多态地创建对象的副本。

让我感到困惑的部分是克隆函数返回接口的指针,这意味着我无法将克隆存储在不同的飞船对象中

通常,重写函数的类型必须与它所覆盖的虚拟函数的类型完全相同。但是,如果要重写的虚函数返回(原始(指针或引用,则对于允许重写函数返回的类型,存在一些约束放宽。

如果是这种情况,重写函数的返回类型可能是指向被重写函数返回指针的类类型的派生类的指针或引用。这称为方法的协变返回类型。

现在,考虑到这一点,并专注于IShipPrototype::clone()虚拟成员功能。它返回一个IShipPrototype*

class IShipPrototype {
public:
virtual IShipPrototype* clone() = 0; // returns IShipPrototype*
// ...
};

由于IShipPrototypeShip的公共基础,覆盖Ship::clone()可以返回Ship*而不是IShipPrototype*

class Ship: public IShipPrototype {
public:
Ship* clone() override; // returns Ship*
// ...
};

这样,如果你有一个Ship对象,并且你直接在它上面调用clone(),你会得到一个Ship*,而不是一个IShipPrototype*——尽管Ship*确实隐式转换为IShipPrototype*IShipPrototype因为它是Ship的公共基类。 这里的IShipPrototypeShip被称为协变类型

请注意,如果通过IShipPrototype接口调用clone(),则返回指针指向的类型的静态类型IShipPrototype*。但是,如果在Ship实例上调用动态类型,则将Ship动态类型

最新更新