3

解析されたVEventオブジェクトとiCalendarファイルに基づいてCalendarオブジェクトを作成するPythonコードがいくつかあります。

カレンダーオブジェクトには、イベントが解析されるときにイベントを追加するメソッドがあります。

次に、ファイルオブジェクト、パス、またはURLからカレンダーを作成するファクトリ関数を作成します。

私はiCalendarpythonモジュールを使用してきました。このモジュールは、次のインスタンスを返すクラスに直接クラスメソッドとしてファクトリ関数を実装します。

cal = icalendar.Calendar.from_string(data)

私がJavaについてほとんど知らないことから、これはJavaコードの一般的なパターンですが、実際にインスタンスをインスタンス化するクラスとは異なるクラスにあるファクトリメソッドへの参照が多いようです。

問題は、これもPythonicと見なされるのかということです。または、ファクトリ関数としてモジュールレベルのメソッドを作成する方がよりPython的であると考えられますか?

4

5 に答える 5

12

[。イベントのコレクションである「Calendar」と、カレンダー上の単一のイベントである「Event」の分離には十分注意してください。あなたの質問では、混乱が生じる可能性があるようです。]

Factoryのデザインパターンには多くのバリエーションがあります。

  1. スタンドアロンの便利な関数(例:calendarMaker(data))

  2. ターゲットクラス(Calendar)を構築する別のクラス(CalendarParserなど)。

  3. クラスレベルのメソッド(Calendar.from_stringなど)メソッド。

これらには異なる目的があります。すべてPythonicで、質問は「どういう意味ですか?」です。と「何が変わる可能性がありますか?」意味がすべてです。変化は重要です。

便利な関数はPythonicです。Javaのような言語は、浮動関数を持つことはできません。孤独な関数をクラスでラップする必要があります。Pythonを使用すると、クラスのオーバーヘッドなしで孤独な関数を使用できます。関数は、コンストラクターに状態の変更や代替戦略、または以前のアクションのメモリがない場合に関連します。

時々、人々はクラスを定義し、次にクラスのインスタンスを作成し、状態と戦略およびその他の構成の通常のパラメーターを設定し、次にクラスの単一の関連するメソッドを呼び出す便利な関数を提供します。これにより、クラスのステートフル性とスタンドアロン関数の柔軟性の両方が得られます。

クラスレベルのメソッドパターンが使用されますが、制限があります。1つは、クラスレベルの変数に依存することを余儀なくされていることです。これらは混乱を招く可能性があるため、機能(ステートフルネスや代替戦略など)を追加する必要がある場合、静的メソッドとしての複雑なコンストラクターで問題が発生します。静的メソッドを拡張しないようにしてください。

2つ目は、クラスのメソッドと属性の残りの部分とはほぼ無関係です。この種はfrom_string、Calendarオブジェクトの多くの代替エンコーディングの1つにすぎません。、、、from_xmlなどfrom_JSONfrom_YAMLあります。これはどれも、カレンダーが何であるか、またはそれが何をするかとの関連性が最も低いものではありません。これらの方法はすべて、送信用にカレンダーをエンコードする方法に関するものです。

成熟したPythonライブラリに表示されるのは、ファクトリが作成するものとは別であるということです。エンコーディング(文字列、XML、JSON、YAMLとして)は、多かれ少なかれランダムに変更される可能性があります。ただし、本質的なことはめったに変更されません。

2つの懸念を分離します。エンコードと表現は、状態と動作からできるだけ離してください。

于 2008-09-22T16:20:38.577 に答える
6

ファクトリパターンのように、どこかで読んで、今ではどこでも使用したいパターンの難解な違いについて考えないのは、Pythonicです。

ほとんどの場合、@ staticmethodをソリューションと考えると、モジュール関数を使用する方がおそらく良いでしょう。ただし、1つのモジュールに複数のクラスを詰め込み、それぞれが同じインターフェイスの異なる実装を持っている場合は、@を使用する方がよいでしょう。 staticmethod

最終的には、@staticmethodまたはモジュール関数によってインスタンスを作成してもほとんど違いはありません。

Pythonで受け入れられている「パターン」の1つは、クラスのファクトリがクラスの初期化であるということであるため、おそらくクラスの初期化子(__init__)を使用します。

于 2008-09-22T16:05:25.537 に答える
2

IMHOモジュールレベルのメソッドは、よりクリーンなソリューションです。これは、「ファクトリ パターン」が一般的に使用される一意の名前空間プレフィックスを与える Python モジュール システムの背後に隠れています。

于 2008-09-22T16:11:52.793 に答える
0

factory パターンには独自の長所と短所があります。ただし、通常、インスタンスを作成する方法を 1 つ選択しても、コードに実際的な影響はほとんどありません。

于 2008-09-22T16:09:45.123 に答える
0

staticmethod が価値を持つことはめったにありませんが、classmethod は役立つ場合があります。クラスとファクトリ関数に実際に何をさせたいかによって異なります。

モジュール内のファクトリ関数は常に「正しい」タイプのインスタンスを作成します(あなたの場合の「正しい」は常に「Calendar」クラスですが、インスタンスを作成しているものの内容に依存させることもできますから)

データではなく、呼び出すクラスに依存させたい場合は、クラスメソッドを使用します。クラスメソッドは、インスタンスなしでクラスで呼び出すことができるという点で staticmethod に似ていますが、最初の引数として呼び出されたクラスを受け取ります。これにより、元のクラスのサブクラスである可能性があるそのクラスのインスタンスを実際に作成できます。classmethod の例は dict.fromkeys() で、キーのリストと単一の値 (デフォルトでは None) から dict を作成します。これは classmethod であるため、dict をサブクラス化すると、'fromkeys' メソッドを完全に無料で取得できます。 . 以下は自分で dict.fromkeys() を書く方法の例です:

class dict_with_fromkeys(dict):
    @classmethod
    def fromkeys(cls, keys, value=None):
        self = cls()
        for key in keys:
            self[key] = value
        return self
于 2008-09-22T16:30:48.503 に答える