ファイルがあるとしますfoo.py
クラスを含むFoo
:
class Foo(object):
def __init__(self, data):
...
次に、生のソースデータから特定の方法でFoo
オブジェクトを作成する関数を追加します。 Fooの静的メソッドとして、または別の別の関数として配置する必要がありますか?
class Foo(object):
def __init__(self, data):
...
# option 1:
@staticmethod
def fromSourceData(sourceData):
return Foo(processData(sourceData))
# option 2:
def makeFoo(sourceData):
return Foo(processData(sourceData))
ユーザーにとって便利であることがより重要であるかどうかはわかりません。
foo1 = foo.makeFoo(sourceData)
または、メソッドとクラスの間の明確な結合を維持することがより重要かどうか:
foo1 = foo.Foo.fromSourceData(sourceData)
代わりに、ファクトリ関数とthirdオプションを選択する必要があります。クラスメソッド:
class Foo(object):
def __init__(self, data):
...
@classmethod
def fromSourceData(klass, sourceData):
return klass(processData(sourceData))
Classmethodファクトリには、継承可能であるという追加の利点があります。これでFoo
のサブクラスを作成でき、継承されたファクトリメソッドはそのサブクラスのインスタンスを生成します。
関数とクラスメソッドのどちらかを選択すると、クラスメソッドを選択します。これは、ファクトリーが生成するオブジェクトのkindを明確に文書化します。これを関数名で明示する必要はありません。これは、複数のファクトリメソッドだけでなく、複数のクラスもある場合に、より明確になります。
次の2つの選択肢を比較してください。
foo.Foo.fromFrobnar(...)
foo.Foo.fromSpamNEggs(...)
foo.Foo.someComputedVersion()
foo.Bar.fromFrobnar(...)
foo.Bar.someComputedVersion()
vs.
foo.createFooFromFrobnar()
foo.createFooFromSpamNEggs()
foo.createSomeComputedVersionFoo()
foo.createBarFromFrobnar()
foo.createSomeComputedVersionBar()
さらに良いことに、エンドユーザーはFoo
クラスだけをインポートし、それをさまざまな方法で使用して、すべてのファクトリメソッドを1か所に置くことができます。
from foo import Foo
Foo()
Foo.fromFrobnar(...)
Foo.fromSpamNEggs(...)
Foo.someComputedVersion()
Stdlib datetime
module はクラスメソッドファクトリを広く使用しており、そのAPIはより明確です。
Pythonでは、通常、ファクトリーメソッドよりもクラス階層を好みます。何かのようなもの:
class Foo(object):
def __init__(self, data):
pass
def method(self, param):
pass
class SpecialFoo(Foo):
def __init__(self, param1, param2):
# Some processing.
super().__init__(data)
class FromFile(Foo):
def __init__(self, path):
# Some processing.
super().__init__(data)
階層全体(この階層のみ)をモジュールに入れます。たとえば、foos.py
。基本クラスFoo
は通常、すべてのメソッド(およびインターフェースなど)を実装し、通常、ユーザーが直接作成することはありません。サブクラスは、ベースコンストラクターを上書きし、Foo
の構築方法を指定する手段です。次に、次のように適切なコンストラクタを呼び出してFoo
を作成します。
foo1 = mypackage.foos.SpecialFoo(param1, param2)
foo2 = mypackage.foos.FromFile('/path/to/foo')
静的メソッド、クラスメソッド、またはモジュールレベルの関数から構築されたファクトリーよりもエレガントで柔軟だと思います。