目录模式和方法链模式 12/30 | Python 主题月

254 阅读2分钟

目录模式和方法链模式 12/30 | Python 主题月

写在前面

本文正在参加「Python主题月」,详情查看活动链接

这个月是 Python 活动月,我决定尝试用 Python 来刷这 30 天的每日一题和随机一题。然后如果周末有精力,我想捣鼓捣鼓这个python-patterns

image.png

设计模式对我来说更多的是学习而不是我的个人经验总结,所以我很可能理解偏,如果有大佬见到了请及时指出,我之所以选择在掘金来写一些个人的东西是因为这里的文章质量更高,我不希望后来者看到了这些文章被误导。

目录模式


class Catalog:
    """catalog of multiple static methods that are executed depending on an init
    parameter
    """

    def __init__(self, param: str) -> None:

        # dictionary that will be used to determine which static method is
        # to be executed but that will be also used to store possible param
        # value
        self._static_method_choices = {
            "param_value_1": self._static_method_1,
            "param_value_2": self._static_method_2,
        }

        # simple test to validate param value
        if param in self._static_method_choices.keys():
            self.param = param
        else:
            raise ValueError(f"Invalid Value for Param: {param}")

    @staticmethod
    def _static_method_1() -> None:
        print("executed method 1!")

    @staticmethod
    def _static_method_2() -> None:
        print("executed method 2!")

    def main_method(self) -> None:
        """will execute either _static_method_1 or _static_method_2
        depending on self.param value
        """
        self._static_method_choices[self.param]()


# Alternative implementation for different levels of methods
class CatalogInstance:

    """catalog of multiple methods that are executed depending on an init
    parameter
    """

    def __init__(self, param: str) -> None:
        self.x1 = "x1"
        self.x2 = "x2"
        # simple test to validate param value
        if param in self._instance_method_choices:
            self.param = param
        else:
            raise ValueError(f"Invalid Value for Param: {param}")

    def _instance_method_1(self) -> None:
        print(f"Value {self.x1}")

    def _instance_method_2(self) -> None:
        print(f"Value {self.x2}")

    _instance_method_choices = {
        "param_value_1": _instance_method_1,
        "param_value_2": _instance_method_2,
    }

    def main_method(self) -> None:
        """will execute either _instance_method_1 or _instance_method_2
        depending on self.param value
        """
        self._instance_method_choices[self.param].__get__(self)()


class CatalogClass:

    """catalog of multiple class methods that are executed depending on an init
    parameter
    """

    x1 = "x1"
    x2 = "x2"

    def __init__(self, param: str) -> None:
        # simple test to validate param value
        if param in self._class_method_choices:
            self.param = param
        else:
            raise ValueError(f"Invalid Value for Param: {param}")

    @classmethod
    def _class_method_1(cls) -> None:
        print(f"Value {cls.x1}")

    @classmethod
    def _class_method_2(cls) -> None:
        print(f"Value {cls.x2}")

    _class_method_choices = {
        "param_value_1": _class_method_1,
        "param_value_2": _class_method_2,
    }

    def main_method(self):
        """will execute either _class_method_1 or _class_method_2
        depending on self.param value
        """
        self._class_method_choices[self.param].__get__(None, self.__class__)()


class CatalogStatic:

    """catalog of multiple static methods that are executed depending on an init
    parameter
    """

    def __init__(self, param: str) -> None:
        # simple test to validate param value
        if param in self._static_method_choices:
            self.param = param
        else:
            raise ValueError(f"Invalid Value for Param: {param}")

    @staticmethod
    def _static_method_1() -> None:
        print("executed method 1!")

    @staticmethod
    def _static_method_2() -> None:
        print("executed method 2!")

    _static_method_choices = {
        "param_value_1": _static_method_1,
        "param_value_2": _static_method_2,
    }

    def main_method(self) -> None:
        """will execute either _static_method_1 or _static_method_2
        depending on self.param value
        """

        self._static_method_choices[self.param].__get__(None, self.__class__)()


def main():
    """
    >>> test = Catalog('param_value_2')
    >>> test.main_method()
    executed method 2!
    >>> test = CatalogInstance('param_value_1')
    >>> test.main_method()
    Value x1
    >>> test = CatalogClass('param_value_2')
    >>> test.main_method()
    Value x2
    >>> test = CatalogStatic('param_value_1')
    >>> test.main_method()
    executed method 1!
    """


if __name__ == "__main__":
    import doctest

    doctest.testmod()

方法链模式


class Person:
    def __init__(self, name, action):
        self.name = name
        self.action = action

    def do_action(self):
        print(self.name, self.action.name, end=" ")
        return self.action


class Action:
    def __init__(self, name):
        self.name = name

    def amount(self, val):
        print(val, end=" ")
        return self

    def stop(self):
        print("then stop")


def main():
    """
    >>> move = Action('move')
    >>> person = Person('Jack', move)
    >>> person.do_action().amount('5m').stop()
    Jack move 5m then stop
    """


if __name__ == "__main__":
    import doctest

    doctest.testmod()

小结

参考文献