全体的な設計:それぞれが共通の書き込み専用インターフェイスとクラス固有の読み取り専用アクセサー関数を持つ型のメンバー変数C
を含む集約クラスがあります(実際にはそのような通常の名前はありません)。各メンバー型は、独自の独立した抽象化を形成し、私のプログラムの他の場所で使用されます。N
M_i, i = 1 ... N
update()
[F]un_i(), [F] = any letter, i = 1 .. N
M_i
集約クラスは、単一のトランザクションですべてのメンバーを更新する必要があるため、すべてのメンバー変数のメンバー関数をupdate()
呼び出す独自の関数があります。update()
// building blocks M_i, i = 1 ... N
class M_1
{
public:
// common write-only interface
void update();
// M_1 specific read-only interface
int fun_1() const;
// ...
int fun_K() const;
private:
// impl
};
// ...
class M_N
{
public:
// common write-only interface
void update();
// M_N specific read-only interface
int gun_1() const;
// ...
int gun_K() const;
private:
// impl
};
// aggregate containing member variables M_i, i = 1 ... N
class C
{
public:
// update all members in a single transaction
void update()
{
m1_.update();
// ...
mN_.update();
}
// read-only interface?? see below
private:
M_1 m1_;
// ...
M_N mN_;
};
質問: 集約クラスのさまざまなメンバー変数のさまざまなメンバー関数にアクセスできますか? 私は3つの選択肢を考えることができます:
代替案 1 : すべてのメンバー変数のすべてのメンバー関数にN * K
デリゲートを書き込むK
N
class C
{
int fun_1() const { return m1_.fun_1(); }
// ...
int fun_K() const { return m1_.fun_K(); }
// ...
int gun_1() const { return mN_.gun_1(); }
// ...
int gun_K() const { return mN_.gun_K(); }
// as before
};
int res = C.fun_5(); // call 5th member function of 1st member variable
代替 2 : すべてのメンバー変数N
にアクセサーを書き込むN
class C
{
M_1 const& m1() const { return m1_; }
// ...
M_N const& mN() const { return mN_; }
// as before
};
int res = C.m1().fun_5(); // call 5th member function of 1st member variable
代替 31
:アクセサ テンプレートをすべてのN
メンバー変数に書き込む
class C
{
public:
enum { m1, /* ... */ mN };
template<std::size_t I>
auto get() const -> decltype(std::get<I>(data_))
{
return std::get<I>(data_);
}
private:
std::tuple<M_1, /* ... */ M_N> data_;
};
int res = C.get<m1>().fun_5(); // call 5th member function of 1st member variable
代替案 1 は、デメテルの法則に違反することを回避しますが、非常に多くの面倒なボイラー プレート コードが必要です (私のアプリケーションでは、N = 5
ラッパーを委譲します)。代替案 2 はラッパーの数を削減しますが、呼び出しコードは少し見苦しく感じます。しかし、そのコードはすべて読み取り専用であり、変更は一貫した集計によってのみ発生する可能性があるため、代替案 2 が代替案 1 よりも望ましい (そして少なくとも安全である) という私の現在の意見です。その場合は、1 つのアクセサーしか使用せず、Alternative 2 と同じ安全性が保証されるため、Alternative 3 が最適な選択となるはずです。K = 3
15
update()
質問: このタイプのコードに適したインターフェイスは何ですか?