我有一个构造函数,它使用内部Builder
对象来实例化一个复杂的对象。数据结构中的五个成员是指针类型。但是,使用此模式时,我遇到了对象被销毁时遇到的问题。以下是我的构造函数的样子,使用成员初始化列表:
Player::Player(const Builder& builder)
:m_name(builder._name)
,m_description(builder._description)
,m_primaryAttributes(builder._primaryAttributes)
,m_abilityAttributes(builder._abilityAttributes)
,m_armor(builder._armor)
,m_weapon(builder._weapon)
,m_inventory(new ComponentMap())
{}
客户端代码运行良好,符合预期:
Player* player = Player::Builder()
.name("Dylan")
.description("Super bad-ass hero of the game")
.primaryAttributes(createPrimaryAttributes())
.abilityAttributes(createAbilityAttributes())
.weapon(createWeapon())
.armor(createArmor())
.build();
但是,如果我省略了消息链中的一个参数,然后销毁我的Player
对象,则会发生错误的事情:
Player* player = Player::Builder()
.name("Dylan")
.description("Super bad-ass hero of the game")
.primaryAttributes(createPrimaryAttributes())
.abilityAttributes(createAbilityAttributes())
.armor(createArmor())
.build();
// ...
delete player;
// ...
// cleanMemory() gets called in Player::~Player()
void Player::cleanMemory()
{
if(m_primaryAttributes != NULL )
delete m_primaryAttributes;
if(m_abilityAttributes != NULL )
delete m_abilityAttributes;
if(m_inventory != NULL )
delete m_inventory;
if(m_weapon != NULL) // oops, bad stuff happens here
delete m_weapon;
if(m_armor != NULL)
delete m_armor;
}
显然,这是因为武器的指针未初始化为NULL
或Weapon
对象的实例。如果从链中省略一个NULL
方法,构造函数似乎也不允许默认值Builder
(至少从我能看到的内容)。目前,客户端必须向Weapon
提供指向NULL
的指针或对象的实例。
如果没有完全修改这个Builder
构造函数,有没有办法解决这个问题?或者,是否应使用其他模式(例如Factory
)重构,然后返回具有位置参数列表的常规构造函数?
答案 0 :(得分:1)
我提到的示例代码不是很好的代码库,我只是建议在build pattern
下面:
class Builder
{
Weapon* BuildWeapon() { return new Weapon(); }
Armor* BuildArmor(); { return new Armor(); }
};
class Player
{
public:
Player(const Builder& builder)
: weapon_ptr(builder.BuildWeapon()),
armer_ptr(builder.BuildArmor())
private:
std::shared_ptr<Weapon> weapon_ptr;
std::shared_ptr<Armor> armor_ptr;
};
用法:
Builder builder;
std::shared_ptr<Player> player(new Player(builder));
或者你可以
class Player2
{
public:
Player() {}
void SetWeapon(Weapon* p) { weapon_ptr.reset(p); }
void SetArmor(Armor* p) { armor_ptr.reset(p); }
private:
std::shared_ptr<Weapon> weapon_ptr;
std::shared_ptr<Armer> armer_ptr;
};
用法:
Builder builder;
std::shared_ptr<Player> player;
player->SetWeapon(builder.BuildWeaper());
player->SetArmor(builder.BuildArmor());
作为weapon_ptr,armer_ptr是智能指针,不再需要为动态分配的内存调用delete
,因此可以删除cleanMemory()
函数。
这只是一个简单的示例,您可以扩展玩家的界面,以便在创建玩家对象后提供构建不同元素的能力。