ダイヤモンドの継承を持つことは悪い習慣と見なされていることを私は知っています. ただし、ダイヤモンドの継承が非常にうまく適合すると感じるケースが 2 つあります。これらの場合にダイヤモンドの継承を使用することをお勧めしますか、それともより良い別のデザインがありますか.
ケース 1:システムでさまざまな種類の「アクション」を表すクラスを作成したいと考えています。アクションは、いくつかのパラメーターによって分類されます。
- アクションは「読み取り」または「書き込み」です。
- アクションは、遅延ありでも遅延なしでもかまいません (1 つのパラメーターだけではありません。動作が大幅に変わります)。
- アクションの「フロー タイプ」は、FlowA または FlowB です。
以下のデザインを予定しています。
// abstract classes
class Action
{
// methods relevant for all actions
};
class ActionRead : public virtual Action
{
// methods related to reading
};
class ActionWrite : public virtual Action
{
// methods related to writing
};
class ActionWithDelay : public virtual Action
{
// methods related to delay definition and handling
};
class ActionNoDelay : public virtual Action {/*...*/};
class ActionFlowA : public virtual Action {/*...*/};
class ActionFlowB : public virtual Action {/*...*/};
// concrete classes
class ActionFlowAReadWithDelay : public ActionFlowA, public ActionRead, public ActionWithDelay
{
// implementation of the full flow of a read command with delay that does Flow A.
};
class ActionFlowBReadWithDelay : public ActionFlowB, public ActionRead, public ActionWithDelay {/*...*/};
//...
もちろん、2 つのアクション (Action クラスから継承) が同じメソッドを実装することはありません。
ケース 2:システムに「コマンド」の複合設計パターンを実装します。コマンドは、読み取り、書き込み、削除などを行うことができます。また、読み取り、書き込み、削除などを行うことができるコマンドのシーケンスも必要です。コマンドのシーケンスには、他のコマンドのシーケンスを含めることができます。
だから私は次のデザインを持っています:
class CommandAbstraction
{
CommandAbstraction(){};
~CommandAbstraction()=0;
void Read()=0;
void Write()=0;
void Restore()=0;
bool IsWritten() {/*implemented*/};
// and other implemented functions
};
class OneCommand : public virtual CommandAbstraction
{
// implement Read, Write, Restore
};
class CompositeCommand : public virtual CommandAbstraction
{
// implement Read, Write, Restore
};
さらに、特別な種類のコマンド、「モダン」コマンドがあります。1 つのコマンドと複合コマンドの両方を最新にすることができます。「モダン」であることにより、特定のプロパティ リストが 1 つのコマンドと複合コマンドに追加されます (両方のプロパティはほとんど同じです)。CommandAbstraction へのポインターを保持し、必要なコマンドの種類に応じて (new を介して) 初期化できるようにしたいと考えています。だから私は(上記に加えて)次のデザインをしたい:
class ModernCommand : public virtual CommandAbstraction
{
~ModernCommand()=0;
void SetModernPropertyA(){/*...*/}
void ExecModernSomething(){/*...*/}
void ModernSomethingElse()=0;
};
class OneModernCommand : public OneCommand, public ModernCommand
{
void ModernSomethingElse() {/*...*/};
// ... few methods specific for OneModernCommand
};
class CompositeModernCommand : public CompositeCommand, public ModernCommand
{
void ModernSomethingElse() {/*...*/};
// ... few methods specific for CompositeModernCommand
};
繰り返しますが、CommandAbstraction クラスから継承する 2 つのクラスが同じメソッドを実装しないようにします。
ありがとうございました。