2

かなり頻繁に他のクラスから派生することを意図したクラスがいくつかあります。それらは、キーダウンレシーバー、キーリリースレシーバー、マウス移動レシーバーなどのユーザー入力レシーバーです。それらを継承するクラスには、たとえば、キー ダウン レシーバーおよびキー リリース レシーバーから継承する hotkey-action や、マウス ムーブ レシーバーから継承する camera-rotator があります。ユーザーが行う入力は、別のクラスによって対応するレシーバーに転送されるため、カメラ回転子などの入力レシーバーは、その転送クラスに自分自身を登録する必要があります。入力を転送するクラスは常に同じで、2 つになることはありません。

私のクラスのユーザーが、マウス移動レシーバーなどから継承するクラスである新しい入力レシーバーを作成する場合、マウス移動レシーバーは、マウス入力を受け取るためにそれ自体を登録するために、転送クラスを知る必要があります。したがって、マウス移動レシーバー コンストラクターのコードは次のようになります。

mouseMoveReceiverIF(inputforwarder* ifo)
{
    ifo.registerInputReceiver(this);
}

inputforwarder が 1 つしかないことは明らかであるため、ユーザーがそれを渡す必要がある場合は直感的でなくなるだけでなく、作成された input-receiver ごとに追加の入力が必要になります。

しかし、inputforwarder をシングルトンまたはグローバル変数にして、ユーザーがコンストラクターで渡す必要なく入力レシーバーがそれにアクセスできるようにすると、他の問題が発生します。ユーザーはそれを知る必要がありました。 inputforwarder は、inputforwarder が作成される前に存在している必要があります。彼に警告するものは何もなく、最初にインプットフォワーダーを作成することを強制するものも何もありません。入力レシーバーが存在しない入力フォワーダーに登録しようとするため、プログラムは単純にクラッシュします。そして、それはさらに悪いことです。

効果的で適切な方法はどのように見えますか? 上記の例に代わるものは何ですか?

ありがとう!

4

4 に答える 4

2

まず、InputForwarder のインスタンスをユーザーから隠す必要があるかどうかについて質問します。これらのコンストラクターを呼び出すユーザー コードは、システムを構成し、依存関係を設定しています。コード、追加のコンストラクター パラメーターを入力することを意味する場合でも、これらの依存関係を明示的に記述する必要があります。

それを非表示にすると仮定すると、入力フォワーダーの作成方法によって異なります。

  • パラメータなしで作成できる場合は、自動開始サービスのようにします。つまり、「the」インスタンスを返す関数があり、関数が呼び出されたときにそれが存在しない場合、関数はそれを作成します。

  • ユーザーが指定したパラメーターを使用する場合、自動開始サービスにはなりません。ユーザーによって設定されたグローバルな「デフォルトの入力フォワーダーインスタンス」を提供し、コンストラクターでこのインスタンスの存在を確認します-存在する場合は、それに登録するか、例外を発生させます。

心配している場合は、ここではおそらくテスト容易性は問題になりません。通常のユーザーから依存関係を隠すグローバルな「デフォルト」インスタンスがある場合でも、次のようなコンストラクターを使用できます。

mouseMoveReceiverIF(inputforwarder* ifo = 0)
{
    if (!ifo) {
        ifo = getDefaultIfo();
        // check for null again if necessary
    }
    ifo.registerInputReceiver(this);
}

そのため、テストに適した任意の inputforwarder を注入できます。

于 2013-03-14T11:13:07.697 に答える
1

シングルトンのinputforwarderを作成し、プログラムの開始時に必ず初期化することができます。そのため、作成前はどのクライアントもアクセスできなくなります。

デザインについてもう1つ、受信者の特殊化にデコレータパターンを使用することを検討することをお勧めします。

編集: そして、ファクトリメソッドがトリックを実行するよりも(ユニットテストなどのために)シングルトンパターンが必要ない場合は、次のようになります:InputReceiverFactory.GetInputReceiver()

于 2013-03-14T10:58:30.653 に答える
1

2 つの提案:

1) 入力フォワーダーを作成する Init 関数/静的クラス メンバーを作成します。これはカプセル化の優れた形式です。

2) inputforwarder クラスを、すべての静的メンバーとプライベート コンストラクターを持つ静的クラスにします。何かを初期化する必要がある場合は、init クラス メソッドを使用して行います。

お役に立てれば。静的クラスは時々悪い習慣だと聞きますが、関数に戻したくない場合は、名前空間が他の唯一の解決策になります。(私が知っていること)

于 2013-03-14T11:01:08.177 に答える
0

あなたのデザインが理解できたら、inputforwarderテンプレートを使ってクラスの一部を作っていただけませんか? 次に、正しいフォワーダーを自動的に呼び出すことができます。

個人的には、単体テストを困難にする傾向があるシングルトンには近づきません。

于 2013-03-14T10:49:01.217 に答える