内部Builder
オブジェクトを使用して複雑なオブジェクトをインスタンス化するコンストラクターがあります。データ構造のメンバーのうち 5 つはポインター型です。ただし、このパターンを使用すると、オブジェクトが破棄されるときに問題が発生します。以下は、メンバーの初期化リストを使用して、コンストラクターがどのように見えるかです。
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();
ただし、メッセージ チェーンで引数の 1 つを省略してから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
ます。コンストラクターは、チェーンから1つのメソッドが省略された場合に、 NULL
(少なくとも私が見ることができるものから)デフォルトを許可していないようです。Builder
現時点では、クライアントはオブジェクトWeapon
へのポインタNULL
またはインスタンスのいずれかを指定する必要があります。
Builder
このコンストラクタを完全に修正せずにこれを回避する方法はありますか? または、これを などの別のパターンを使用してリファクタリングしFactory
、位置パラメーター リストを使用して通常のコンストラクターに戻す必要がありますか?