1

次のように定義された、ユーザーオブジェクトのメソッドのリストがあります。

METHOD_ATTACK: {
    'func': User.handle_attack,
    ...
}

これらのアクションを処理するときは、次のように呼び出します。

user.handle_action(ACTION, *args)

これの目的は、さまざまな機能に対する制御を抽象化する METHOD_* ディクショナリにさまざまな制御パラメーターがあることです。たとえば、アクションを続行できるようにするためにユーザーが特定の状態にある必要があるものなどです。すべてがパスした場合、handle_action は、アクション メソッドを呼び出してアクションを実行する前に、これらの条件をチェックします。

ここで、User の 2 番目のタイプを作成し、これらのメソッドのいくつかを派生クラスでオーバーライドしたいので、User.handle_attack が存在する場合は、User.handle_attack の代わりに SpecialUser.handle_attack を呼び出します。

1 つのオプションは次のとおりです。

METHOD_ATTACK: {
    'func': "handle_attack",
    ...
}

...

func = getattr(user, ACTION["func"])

これにより、すべてのアクションを検索するための getattr 呼び出しが追加されます。

別のオプションは、SpecialUser のすべての METHOD_* を複製することですが、これは冗長に感じます。

この変更に最適な設計はどれですか?

4

1 に答える 1

4

一般的なイディオムの 1 つは、これらをプレフィックス付きのクラスのメソッドとして持つことです。

class User(object):
    def action_attack(self):
        ...

    def handle_action(self, name):
        method = getattr(self, 'action_' + name)
        method()

class SpecialUser(User):
    def action_attack(self):
        ...

ところで、オブジェクト指向プログラミングとは、オブジェクトが自分の状態を認識し、メッセージに基づいて動作することを意味します。コントロールをオブジェクトの外側に置くことで、このメカニズムを実際に打ち負かしています。したがって、ユーザーのメソッド内で正しい状態をチェックするだけです。状態が辞書に記載されている場合でも、オブジェクト内で確認してください。

于 2013-08-15T03:15:38.517 に答える