Skip to main content
 首页 » 编程设计

python之这是工厂模式的正确实现吗

2025年05月04日19kenshinobiy

首先,这不是作业。其次,它有点长。抱歉并提前感谢您的耐心等待。

有一个.. 游戏,基本上它为您提供了一个开始条件、一个期望的结果、一组进程和最大进程数。工作是找到执行过程的正确顺序,以便获得所需的结果。
所以我觉得用电脑来解决问题可能会好些。最大步长通常在 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()方法中添加几行就可以了。但是我对此仍然没有信心。 我的问题(最后!)是:

  1. 这个实现在 Python 中是否正确,甚至过度?
  2. 在 process_factory() 方法中,“if...elif...”变得很长,我想把它做成字典。如下所示:

    methods = {'A': ProcessA(), 'B': ProcessB() }

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

  3. 一段时间后,出现了一种新的进程类型,它不会改变输入,但会改变进程之后的行为方式。
    例如,ProcessA 是输入加 1,ProcessB 是减 1。但是在 ProcessC 之后,ProcessA 变成加 2,ProcessB 变成减 2。我不能直接修改 ProcessA,因为原始副本需要在下一个循环。 我的解决方案是:

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

    • 改变整个逻辑,使一个过程不仅影响输入,而且影响其他参数(例如可用的过程,甚至结果)。但是会有很大的变化,我需要考虑如何在创建新的更改版本的流程的同时维护旧的流程副本。

    您认为最好的解决方案应该是什么?

请您参考如下方法:

正如您所说,字典是比多个 if 更好的解决方案。您可以通过 classes 本身的值来避免实例化每个对象,它们是 Python 中的一流对象;然后你可以实例化字典查找的结果:

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