2016-05-13 5 views
2

私はデザインパターンで自分のスキルを向上させようとしていますので、簡単にしてください:)私の仕事では、アルゴリズムが定義されている問題に対処しなければならないことがよくあります。適用するデザインパターンは?

私はカウンタークラスを持っているとしましょう。カウンタークラスは、特定の条件に一致するアイテムを単純にカウントすることです(大きな単純化)。これらの項目は、そう例えば、異なる構造を有していてもよい:

  • のカウンターが「テキスト」の項目のために実行されている場合、カウンタは "のために実行されている場合、その長さはX
  • よりも大きい場合は、私が唯一の項目を数えます「画像」アイテムの場合は、JPEG画像の場合にのみアイテムをカウントします。

これは、カウンタが上に働くだろうAbstractItemクラスを持っている(私のために)右に感じるが、基準はアイテムの種類ごとに異なる方法で評価されているので、それはまた、関連するAbstractCriteriaを必要とします。

擬似コードのいくつかの並べ替え:

class Counter 
{ 
    AbstractItemFactory factory; // initialized in constructor 
    AbstractCriteria criteria; // initialized in constructor 
    DataProvider provider;  // initialized in constructor 

    int count() 
    { 
    int result; 

    while((Data data = provider.get()) != null) 
    { 
     AbstractItem item = factory.create(data); 
     if(criteria.match(item)) 
     { 
     result++; 
     } 
    } 
    return result; 
    } 
} 

ここでの問題はもちろんAbstractCriteriaAbstractItemを処理する方法を知らないだろうということです。オーバーライドされたmatch()メソッドの中でベースから派生したキャストを使用してこれを解決することは可能ですが、それは非常に良い設計ではありません。テンプレートを使用することも可能ですが、コードが複雑になるため、私が望むことを達成するために使用できるデザインパターンがあるかどうかを最初に知りたいのです。あるいは、この問題に対する私のアプローチはまったく間違っていて、私が見逃しやすい簡単な解決策がいくつかあります。

ありがとうございます!

+0

どう一部functionnalプログラミング手法を借り程度とのcriterias(基本的には関数参照)を表現するためにブールラムダ式を使うのか?たとえばJSでは、次のように簡単になります。 'function filteredCount(items、filter){ return items.filter(filter).length;} filteredCount([1,2,3]、function(num){return num%2}); – plalx

+0

条件をハードコードすることはできますか?あるいは、再コンパイルせずに、つまり設定ファイルを通して基準を更新できるようにしたいですか? – denniskb

+0

@plalx残念ながら、私は型付き言語を使用していますので、 'function(num)'と 'function(str)'は2種類あります。それらを使うために、私はそれらをいくつかの一般的なタイプから継承させなければなりません。私の例では、 'AbstractItemFactory'によって生成された項目の内容について何も知らないので、パラメータとして抽象型を受け入れる必要があります。この時点で私は元の問題に戻ってきました。これらの関数の中で抽象型を派生したものに戻す必要がありました。それを回避したいと思います: – xba

答えて

0

:)

+0

Visitorパターンは、データ構造があり、新しい操作を追加することができます。標準的な例は構文木であり、ツリー上で操作を行いたいとします。しかし、一連のアルゴリズムが閉じられ、データ構造が変更されると、Visitorパターンは悪い選択です。データ構造を変更すると、すべての訪問者が変更されることになります。新しいノードタイプを追加するとき。 – Jens

+0

いくつかのコード/詳細を共有するのに気をつけますか? – denniskb

+0

@Jens私のコードでは、訪問者の数が常に「要素」の数よりもずっと少ないため、これはかなりうまく機能しました。それ以外にも、ビジタークラスは1つの「要素」クラスのみを処理する必要があります(つまり、クラスが異なる場合はエラーです)。だから私は実際に訪問者パターンの修正版を使用しました。たぶんそれは二重ディスパッチです。しかし、私が言ったように、パターンの私のスキルはあまり良くはないと私はそれらを改善しようとしているので、あなたはより良い解決策を持っている場合、私は見て幸せになります:) – xba

0

KISS

template<typename T> 
bool predicate(T const & val); 

template<> 
bool predicate<string>(string const & s) { 
    return s.length() > 5; 
} 

template<> 
bool predicate<Image>(Image const & i) { 
    return i.format() == "JPEG"; 
} 

template<class Iter> 
iterator_traits<Iter>::difference_type count(Iter first, Iter last) { 
    using element_type = decay<iterator_traits<Iter>::value_type>::type; 
    return count_if(first, last, predicate<element_type>); 
} 

名前空間にこれらを入れたり、好きな場合は、それらカウンタクラスの静的メソッドにします。私はVisitorパターンを使用して私の問題を解決し、エンドで

+0

これはコードのほんの一片です。私のライブラリに確実に保管します:)ここに2,3の 'typename'を追加してコンパイルすることができました。ただし、特定のタイプのコンテナのイテレータを渡す場合にのみ機能します。私の場合、 'AbstractItemFactory'は' AbstractItem'(これはあなたの例では文字列とImageの親クラスになります)ので、何か明白なことがない限り私たちは正方形に戻っています...? – xba

+0

@xbaあなたのAbstractItemの動的/実数/派生型をクエリする方法はありますか? – denniskb

+0

こんにちは、もちろん可能ですが、私はちょうどそれがかなりコストのかかる操作であるため避けたかったのです:)最後にビジターパターンを使用して解決しました:) – xba

関連する問題