使いやすい抽象ファクトリを実装する際に問題があります。具体的な工場をこのように定義することができるようにメタクラスを使用したPythonのファクトリパターン実装
ゴール
:
class MyConcreteFactory(...):
@classmethod
def __load(cls, key):
obj = ... # Loading instructions here
return obj
concretreファクトリを使用できるようにするには、このよう
obj = MyConcreteFactory[key]
私の試み
私が試しましたブラケット演算子をオーバーライドしてカプセル化するファクトリのメタクラスを定義する電子工場パターン:と呼ばれる__loadメソッドはメタクラスではなく具体的なクラスから1から1であるので、
class __FactoryMeta(type):
__ressources = {}
@classmethod
def __getitem__(cls, key):
if key not in cls.__ressources:
cls.__ressources[key] = cls.__load(key)
return cls.__ressources[key]
@classmethod
def __load(cls, key):
raise NotImplementedError
class ConcreteFactory(metaclass=__FactoryMeta):
@classmethod
def __load(cls, key):
return "toto"
a = ConcreteFactory["mykey"]
print(a)
問題
これが失敗しました。結果は次のとおりです。
Traceback (most recent call last):
File "C:\Users\walter\workspace\Game\src\core\factories.py", line 34, in <module>
a = ConcreteFactory["mykey"]
File "C:\Users\walter\workspace\Game\src\core\factories.py", line 19, in __getitem__
cls.__ressources[key] = cls.__load(key)
File "C:\Users\walter\workspace\Game\src\core\factories.py", line 24, in __load
raise NotImplementedError
NotImplementedError
私は、メタクラスから__loadメソッドを削除しようとしたが、その後、私はこの(予測可能な)エラーました:
Traceback (most recent call last):
File "C:\Users\walter\workspace\Game\src\core\factories.py", line 30, in <module>
a = ConcreteFactory["mykey"]
File "C:\Users\walter\workspace\Game\src\core\factories.py", line 19, in __getitem__
cls.__ressources[key] = cls.__load(key)
AttributeError: type object '__FactoryMeta' has no attribute '_FactoryMeta__load'
質問
をアクセスする方法はありますメタクラスのクラスメソッド? 私は間違っていますか、これを別の方法で行うべきですか?それでは?
ソリューション
class __FactoryMeta(type):
ressources = {}
def __getitem__(cls, key):
if key not in cls.ressources:
cls.ressources[key] = cls.load(key)
return cls.ressources[key]
def load(cls, key):
raise NotImplementedError
class ConcreteFactory(metaclass=__FactoryMeta):
@classmethod
def load(cls, key):
return "toto"
a = ConcreteFactory["mykey"]
print(a)
少なくともあなたの問題の一部は名前のマングリングです。 http://stackoverflow.com/q/7456807/3001761 – jonrsharpe
メタクラスは二重のアンダースコアが悪い習慣ではない(ほとんど)唯一の例ですか? –
Jonが正しい。 '__name'は、スーパークラスにアクセスできないようにするために、インタプリタが手のひらになってしまいます。 '__load'を' _load'に変更すると、_that_エラーが取り除かれます(サブクラスで '__getitem__'をどのように使うかによって' __resources'もあるかもしれませんが)。 – mgilson