Python 这是工厂模式的正确实施吗?

Python 这是工厂模式的正确实施吗?,python,design-patterns,Python,Design Patterns,首先,这不是家庭作业。第二,它有点长。对不起,谢谢您的耐心等待 有一个。。游戏,基本上它为你提供了一个开始的条件,一个期望的结果,一系列的过程和最大数量的过程。任务是找到正确的流程执行顺序,以获得所需的结果。 所以我认为用计算机来解决这个问题可能是件好事。最大步长通常小于10,因此使用蛮力应该是安全的 下面是我的解决方案代码(顺便说一句,它是用python编写的)。简单地说,我为每个进程创建一个对象,并将它们放入一个列表中。在每个步骤中,我遍历列表,将参数(起始条件、预期结果等)传递给流程对象,

首先,这不是家庭作业。第二,它有点长。对不起,谢谢您的耐心等待

有一个。。游戏,基本上它为你提供了一个开始的条件,一个期望的结果,一系列的过程和最大数量的过程。任务是找到正确的流程执行顺序,以获得所需的结果。
所以我认为用计算机来解决这个问题可能是件好事。最大步长通常小于10,因此使用蛮力应该是安全的

下面是我的解决方案代码(顺便说一句,它是用python编写的)。简单地说,我为每个进程创建一个对象,并将它们放入一个列表中。在每个步骤中,我遍历列表,将参数(起始条件、预期结果等)传递给流程对象,并检查输出是否与预期结果匹配。如果匹配,则返回被调用进程的堆栈

class Puzzle:
    def __init__(self, initial_num, num_steps, result, list_process):
        self.initial_num = initial_num
        self.num_steps = num_steps
        self.result = result
        self.list_process = list_proces

    def solve(self):
        for process in self.list_process:
            stack = process.run(self.initial_num, self.num_steps, self.result, self.list_process)
            if stack is not None:
                return stack
        return None
对于流程,因为有许多类型的流程,并且在每种情况下都有不同的流程组合要执行。我碰巧使用了一点Java,所以我使用了多态性的思想,这在python中并不是真正需要的,但我认为它是一个整洁的结构

class ProcessBase:

    @property
    def name(self):
        print("need to rewrite")

    def do_process(self, num_input):
        print("need to rewrite")

    def run(self, input_, steps_remain, result, processes_next):
        if steps_remain is 0:
            return None
        try:
            output= self.do_process(input_)
        except RuntimeError:
            return None
        if output == result:
            stack = [self.name]
            return stack
        for process in processes_next:
            stack = process.run(output, steps_remain - 1, result, processes_next)
            if stack is not None:
                stack.append(self.name)
                return stack
        return None

class ProcessA(ProcessBase):

    def __init__(self, param):
        super().__init__()
        self.param = param

    @property
    def name(self):
        return "ProcessA" + self.param

    def do_process(self, input):
        # do the process(e.g. add 1 to the input)
        output = input + 1
        return output
所以基本上,run()在每个进程中都是相同的,所以我只需要重写name()来显示调用堆栈,而do_process()用于实际进程。然后我的工厂方法(它不是一个类,因为我认为不需要多个工厂)如下所示

def process_factory(str_input):
    if str_input=="A":
        return ProcessA()
    elif str_input=="B":
        return ProcessB()
    # etc
因此,在实际使用它时,我可以保持大部分代码不变。当有新类型的进程时,我只需要添加一个新类,覆盖name()和do_process(),在process_factory()方法中添加几行就可以了。但是我仍然没有信心。 我的问题(最后!)是:

  • 这个实现是否正确,或者在Python中是否过度
  • 在process_factory()方法中,“if…elif…”变得相当长,我想把它做成一本字典。如下图所示:

    方法={'A':ProcessA(), “B”:进程B() }

    但这意味着即使未使用,也将创建所有对象。我还可以将dict中的构造函数替换为一个返回对象的方法,但是当我需要添加另一种类型的进程时,我需要写更多的行。有更好的办法吗

  • 一段时间后,出现了一种新类型的流程,它不会改变输入,但会改变流程之后的行为方式。
    例如,假设ProcessA将向输入中添加1,ProcessB将负1。但在ProcessC之后,ProcessA变为加法2,ProcessB变为减法2。我不能直接修改ProcessA,因为原始副本需要在下一个周期中重新使用。 我的解决办法是:

    • 添加一个新的ProcessC类并重写run()方法。它对原始代码的更改最少,但有点违背了原始结构的理念

    • class ProcessBase:
      
          @property
          def name(self):
              print("need to rewrite")
      
          def do_process(self, num_input):
              print("need to rewrite")
      
          def run(self, input_, steps_remain, result, processes_next):
              if steps_remain is 0:
                  return None
              try:
                  output= self.do_process(input_)
              except RuntimeError:
                  return None
              if output == result:
                  stack = [self.name]
                  return stack
              for process in processes_next:
                  stack = process.run(output, steps_remain - 1, result, processes_next)
                  if stack is not None:
                      stack.append(self.name)
                      return stack
              return None
      
      class ProcessA(ProcessBase):
      
          def __init__(self, param):
              super().__init__()
              self.param = param
      
          @property
          def name(self):
              return "ProcessA" + self.param
      
          def do_process(self, input):
              # do the process(e.g. add 1 to the input)
              output = input + 1
              return output
      
    • 更改整个逻辑,使流程不仅影响输入,还影响其他参数(例如可用流程,甚至结果)。但是会有很多变化,我需要考虑如何在创建新的流程修改版本的同时维护流程的旧副本

    你认为什么是最好的解决方案


  • 正如你所说,一本字典比多个如果更好。您可以通过让类本身拥有值来避免实例化每个对象,这些值在Python中是第一类对象;然后,您可以实例化dict查找的结果:

    methods = {'A': [ProcessA, [param1, param2]], 'B', [ProcessB, [param3, param4], ...}
    klass, params = methods[str_input]
    return klass(*params)
    

    正如你所说,一本字典比多个如果更好。您可以通过让类本身拥有值来避免实例化每个对象,这些值在Python中是第一类对象;然后,您可以实例化dict查找的结果:

    methods = {'A': [ProcessA, [param1, param2]], 'B', [ProcessB, [param3, param4], ...}
    klass, params = methods[str_input]
    return klass(*params)
    
    (1) 我觉得你的实现很好,但我不是专家

    对于名称类属性,可以使用
    \uuuu str\uuu
    \uuu repr\uuu
    方法

    
    类ProcessBase:
    定义报告(自我):
    返回f“{self.\uuuuuu类{uuuuuuu名称}参数:{self.param}”
    定义(自我):
    返回自我报告__
    
    这样,bo每次都需要重新命名

    (2) 如前所述,我还将使用dict

    def过程工厂(str输入): 方法={A':进程A,'B',进程B,…} 返回方法[str_input]() 你在拼图中的解题方法成了

    def求解(自):
    对于self.list\u流程中的流程信:
    过程=过程工厂(过程字母)
    stack=process.run(self.initial\u num、self.num\u步骤、self.result、self.list\u进程)
    如果堆栈不是无:
    返回堆栈
    一无所获
    
    (3) 您可以使用与以前相同的结构实现
    ProcessNewBase
    以及
    ProcessNewA
    B
    等。在这里,您可以创建一个独特的dict,使用新旧流程。这样,在您的谜题中,您可以设置是否要使用旧流程或新流程,或者甚至实现同时使用这两种流程的解决方案

    (1)我觉得您的实现不错,但我不是专家

    对于名称类属性,可以使用
    \uuuu str\uuu
    \uuu repr\uuu
    方法

    
    类ProcessBase:
    定义报告(自我):
    返回f“{self.\uuuuuu类{uuuuuuu名称}参数:{self.param}”
    定义(自我):
    返回自我报告__
    
    这样,bo每次都需要重新命名

    (2) 如前所述,我还将使用dict

    def过程工厂(str输入): 方法={A':进程A,'B',进程B,…} 返回方法[str_input]() 你在拼图中的解题方法成了

    def求解(自):
    对于self.list\u流程中的流程信:
    过程=过程工厂(过程字母)
    堆栈=进程运行(self.initial\u nu