他のオブジェクトを集約するオブジェクトを作成する場合、パススルー関数を使用して内部オブジェクトへのインターフェイスを公開するのではなく、内部オブジェクトへのアクセスを許可したいと思います。
たとえば、2つのオブジェクトがあるとします。
class Engine;
using EnginePtr = unique_ptr<Engine>;
class Engine
{
public:
Engine( int size ) : mySize( 1 ) { setSize( size ); }
int getSize() const { return mySize; }
void setSize( const int size ) { mySize = size; }
void doStuff() const { /* do stuff */ }
private:
int mySize;
};
class ModelName;
using ModelNamePtr = unique_ptr<ModelName>;
class ModelName
{
public:
ModelName( const string& name ) : myName( name ) { setName( name ); }
string getName() const { return myName; }
void setName( const string& name ) { myName = name; }
void doSomething() const { /* do something */ }
private:
string myName;
};
EngineとModelNameの両方で構成されるCarオブジェクトが必要だとします(これは明らかに工夫されています)。そうするための1つの可能な方法は、これらのそれぞれにアクセス権を与えることです
/* give access */
class Car1
{
public:
Car1() : myModelName{ new ModelName{ "default" } }, myEngine{ new Engine{ 2 } } {}
const ModelNamePtr& getModelName() const { return myModelName; }
const EnginePtr& getEngine() const { return myEngine; }
private:
ModelNamePtr myModelName;
EnginePtr myEngine;
};
このオブジェクトを使用すると、次のようになります。
Car1 car1;
car1.getModelName()->setName( "Accord" );
car1.getEngine()->setSize( 2 );
car1.getEngine()->doStuff();
別の可能性は、次のように、内部オブジェクトの(必要な)関数ごとにCarオブジェクトにパブリック関数を作成することです。
/* passthrough functions */
class Car2
{
public:
Car2() : myModelName{ new ModelName{ "default" } }, myEngine{ new Engine{ 2 } } {}
string getModelName() const { return myModelName->getName(); }
void setModelName( const string& name ) { myModelName->setName( name ); }
void doModelnameSomething() const { myModelName->doSomething(); }
int getEngineSize() const { return myEngine->getSize(); }
void setEngineSize( const int size ) { myEngine->setSize( size ); }
void doEngineStuff() const { myEngine->doStuff(); }
private:
ModelNamePtr myModelName;
EnginePtr myEngine;
};
2番目の例は次のように使用されます。
Car2 car2;
car2.setModelName( "Accord" );
car2.setEngineSize( 2 );
car2.doEngineStuff();
最初の例に対する私の懸念は、プライベートメンバーに直接アクセスを与えることにより、OOカプセル化に違反することです。
2番目の例についての私の懸念は、クラス階層の上位レベルに到達すると、非常に大きなパブリックインターフェース(SOLIDの「I」に違反)を持つ「神のような」クラスに巻き込まれる可能性があることです。
2つの例のどちらが優れたOO設計を表していますか?または、両方の例がOOの理解の欠如を示していますか?