2017-06-19 2 views
0

私は手紙を進めたアプリを書くことに決めました。 は、だから私は概念を表すクラスを細工:クラスにさらに多くの状態を追加することを避けるにはどうすればよいですか?

class Letter 
{ 
    //implementation1 
}; 

その後、私は、私は、このような「処理」などの文字のためのいくつかの「フラグ」を追加する必要があることに気づき、「処理」、「wont_be_processed」。

class Letter 
{ 
    //implementation1 
    state letter_state_; 
}; 

そして、すべての文字がいくつかのコンテナに格納されているとします。
(上記の状態は実装には、 であり、ビジネスロジックの一部ではないことを明確にしておきたい)
最後に、別の特別なフラグが必要であることを理解しました。コンテナに格納されているすべてのオブジェクト。

だから、私が今見ているさらに進行する方法を2つの素朴な方法があります。
1)は、別のフラグを追加します。
2)別のフィールドを追加します。
"処理中"、 "処理済み"、 "未処理"はどういう関係であっても、新しい状態はそれらに適切に関連しないため、最初のオプションは不自然になります。 2番目のオプションはクラスの拡張につながります。また、私の同僚は新しいフィールドを追加するのが好きではありません(しかし、根拠を証明することなく)。

このような設計の落とし穴や問題を解決するための標準的な方法はありますか?

Upd。追加された例。

void process_letter(Letter& foo) 
{ 
    if(foo.latter_state_ == states::wont_be_processed) 
     return; 

    if(foo.letter_state_ == states::processed) 
     process_impl_1(foo); 

} 

たのでしょうか?

void process_letter(Letter& foo) 
{ 
    if(foo.latter_state_ == states::wont_be_processed 
     && foo.new_spacial_state_ != special_state::bar) 
     return; 

    if(foo.letter_state_ == states::processed) 
     process_impl_1(foo); 

} 

UPD2
はたぶん、全体のデザインは完全に間違っています。もしそうなら、質問を閉じるべきですか?

+0

新しい状態が有効な場合は元の状態は適用されません.2)元の状態は新しい状態とは独立しており、適用されている可能性があります。 1)の場合は新しい状態です。 2)の場合は、新しいフィールドです。 – stark

+0

それは第2のケースです。しかし、クラスがかなり大きいと仮定し、新しいフィールドを正しく処理するためにコンストラクタに新しいコード行を追加する必要があります。また、クラスのシリアル化を担当するコードを変更する必要があります。新しいフィールドを追加すると、異なるファイルが変更されます。一方、このフィールドの唯一の消費者は、1つの方法で1つの「if」になります。そのような「順応」のために新しいフィールドを追加することを止めるべき行がありますか? –

+0

恐らく、「州」という言葉の使用は誤解を招きます。私はちょうどこのプロパティに基づいて処理するために、何らかの形で文字にプロパティを割り当てる必要があります。しかし、私は別の文字の新しいクラスを導入し、それらを作成するためのファクトリを書きたいとは思わない。また、私は動的多型を使用しないようにしています。 –

答えて

0

私は2つのアイテムをお勧めします:ここでの考え方は、それが変化の最小量を持つようにコードを作ることです

状態テーブルを使用した状態に

  • を列挙

    1. を。状態データをテーブルに配置すると、実行可能コードの変更量を最小限に抑えてテーブルを拡張できます。

      状態テーブルには、多くの実装があります。たとえば、インターネットで "state design pattern C++"を検索します。

      良い本やリファレンスが列挙に役立ちます。

      編集1:Stateテーブルの例
      あなたは[状態-ID、関数ポインタ]のテーブルを持つことができます。

      struct State_Entry 
      { 
          unsigned int state_id; 
          void (*Ptr_State_Processing_Function)(unsigned int state_id); 
      }; 
      

      テーブルに状態のIDを配置する便利な機能があることです状態は連続的でも均質である必要もありません。また、関数ポインタの型をシンプルに保つことによって、異なるシグネチャを持つ関数の問題を取り除くことができます(関数ポインタは同じ型/シグネチャでなければなりません)。

  • +0

    ありがとうございます! enumまたはより一般的な抽象列挙を使用することを意味する状態を列挙することによって? 問題は、おそらく、私の質問では適切に対処できませんでした。私はすでに1つの州のグループを持っており、他の国と揃っていない新しい州を追加する必要があります。私は "状態パターン"について読んでいますが、私はそれが "非均質"状態にどのように直面しているのか理解していません。 –

    +0

    最初の列挙値が既存の 'enum'の最後の値である新しいリストを作成できます。 –

    +0

    最も基本的な状態テーブルは、状態IDと状態を処理する関数へのポインタを含む構造のテーブルです。あなたは、ファンクタを使用してより多くのファンシーを得ることができます。 –

    関連する問題