2009-04-29 9 views
4

私は、アカウントとオペレータの2つのクラスを持っています。アカウントにはオペレーターのリストが含まれています。今、オペレータ(リスト内の)がメッセージを受け取るたびに、ビジネスロジックを実行するAccountオブジェクトに通知する必要があります。通知するコンテナオブジェクト:ベストプラクティス

1)コンテナ[アカウント]オブジェクトへのオペレータ内の参照を保持し、直接メソッドを呼び出します。

は、私はこれを達成するためにどのように3つの選択肢を考えます。循環参照のために絶対に良いわけではありません。

2)イベントを使用します。私が知る限り、Pythonには組み込みのイベント処理機構はありません。だから、これは実装するのが少し難しいです。

3)オペレータに直接メッセージを送信しないでください。代わりに、Accountsのみを処理し、内部的にはハンドラ演算子を使用します。この場合、私は演算子への参照を渡すことができないので、これは少し制限しています。

アーキテクチャの観点から、どのアプローチが最も有利なのでしょうか。どのようにこのタスクを処理しますか?

Pythonでスニペットを指摘できれば幸いです。

答えて

5

あなたはこれをよく考えています。真剣に。 PythonはC++ではありません。あなたの懸念事項はPythonでは問題ではありません。あなたの問題のドメインに意味をなさないものを書いてください。

"循環参照のために絶対に良いわけではありません。"

どうしてですか?円は、ここでは全く関係がありません。双方向の関係は素晴らしいことです。それらを使用してください。 Pythonのガベージコレクションは、あなたのことを考えずに、それらをうまく収集します。

どのような問題が相互(双方向)関係でありますか?

"...操作はアカウントとその内部ではハンドラ演算子です。この場合は演算子の参照を渡すことができないため、これは少し制限があります。あなたのオペレータは、Pythonオブジェクトとは何ですか? 」

は、あなたが望むすべてを渡す。すべてのPythonオブジェクトは、(実質的に)参照で、それを悩む必要はありません。

あなたはオペレータオブジェクトを操作で可能どのような問題がありますか?あなたはインスタンスメソッドについて知らないかもしれない

+0

+1 - Python 2.5を使用していて__del__メソッドを定義していない限り、循環参照はちょうど大きくありませんもう取引する。 –

+1

@ Jason Baker:Pythonを7年間使用していましたが、__del__メソッドを決して定義していませんでした。双方向関係に問題はなかったので、定期的に使用してください。彼らは2.2まで偉大な仕事をしました。 –

+0

これは、すべての循環参照を追跡していることはわかりませんでした。しかし、何らかの理由で__del__メソッドを定義するとどうなりますか?私はまだそれらを手動で追跡する必要があります、そうですか? –

3

Observerパターンには「one-size-fits-all」ソリューションはありません。しかし、通常、関心のある当事者が特定のイベントに対して自分自身を登録し、発生したときにこれらのイベントを投稿できるEventManagerオブジェクトを定義する方が良いでしょう。単純に依存関係を少なくします。

グローバルなEventManagerインスタンスを使用する必要があることに注意してください。これは、テスト中や一般的なOOの観点から問題になる可能性があります(グローバル変数)。私はあなたのコードが混乱するので、常にEventManagerを渡すことを強くお勧めします。

私自身のコードでは、イベントを登録するための「キー」はイベントのクラスです。 EventManagerはディクショナリ(イベントクラス→オブザーバのリスト)を使用して、どのイベントがどこに行くかを知ることができます。通知コードでは、dict.get(event.__class__,())を使用してリスナーを見つけることができます。

+0

感謝。 –

3

私はこのためにイベント処理を使用します。あなたは自分で実装する必要はありません - 私はpydispatcherをこの種のイベント処理に使用しています。常にうまく働いています(内部的に弱参照を使用して循環参照の問題を回避しています)。

また、guiフレームワークを使用している場合は、すでにフックできるイベントフレームワークがある可能性があります。たとえば、PyQtにはシグナルとスロットがあります。

+0

+1とpydispatcherの関係使い方が簡単で、説明した状況を正確に解決するために設計されています。それは、あなたがそれを必要とすれば、他のコンテナの中に演算子を接続できるように、オブジェクトを切り離します。 –

3
>>> class Account(object): 
...  def notify(self): 
...   print "Account notified" 
... 
>>> class Operator(object): 
...  def __init__(self, notifier): 
...   self.notifier = notifier 
... 
>>> A = Account() 
>>> O = Operator(A.notify) 
>>> O.notifier() 
Account notified 
>>> import gc 
>>> gc.garbage 
[] 
>>> del A 
>>> del O 
>>> gc.garbage 
[] 

ことの一つは、ドット構文を使用する場合に見上げたとき、それらが結合していることである。言い換えれば、自動的にA.notifyを言ってあなたはその後、保持することができますA.に通知の自己パラメータをバインド回収不能なゴミを発生させずにこの関数への参照。

最後に、このタイプのものには常にKamaeliaを使用できます。

+0

うわー、コードスニペットと非常に明確な説明に感謝します。非常に面白いアプローチ。 –

0

Web上にオブザーバーパターンスニペットがあります。信頼性の高いコードの良い情報源は、例えば、アクティブ状態である:パターンの名前を思い出させるため

http://code.activestate.com/recipes/131499/

関連する問題