修复 Python 中的抽象工厂

huangapple go评论68阅读模式
英文:

Fixing Abstract Factory in Python

问题

I'm trying to implement Abstract Factory pattern in Python, but after creating new "product" it simply does not work and I can't figure out what's the problem. Here's a code:

from __future__ import annotations
from abc import ABC, abstractmethod

# AbstractFactory
class AbstractCarFactory(ABC):
    @abstractmethod
    def create_product_car(self) -> AbstractProductCar:
        pass

    @abstractmethod
    def create_product_engine(self) -> AbstractProductEngine:
        pass

    @abstractmethod
    def create_product_wheel(self) -> AbstractProductWheel:
        pass

class FordFactory(AbstractCarFactory):
    def create_product_car(self) -> AbstractProductCar:
        return Ford()

    def create_product_engine(self) -> AbstractProductEngine:
        return FordEngine()

    def create_product_wheel(self) -> AbstractProductWheel:
        return FordWheel()

# ... (rest of the code)

if __name__ == "__main__":
    print("Client: Testing first factory:")
    client_code(FordFactory())

    print("Client: Testing second factory:")
    client_code(ToyotaFactory())

    print("Client: Testing third factory:")
    client_code(MercedesFactory())

I've already tried to create abstract client code instead of copying it every time but it doesn't help. Even ChatGPT can't tell what's the matter lol

英文:

I'm trying to implement Abstract Factory pattern in Python, but after creating new "product" it simply does not work and I can't firuge out what's the problem. Here's a code:

`from __future__ import annotations
from abc import ABC, abstractmethod
# AbstractFactory
class AbstractCarFactory(ABC):
@abstractmethod
def create_product_car(self) -> AbstractProductCar:
    pass

@abstractmethod
def create_product_engine(self) -> AbstractProductEngine:
    pass

@abstractmethod
def create_product_wheel(self) -> AbstractProductWheel:
    pass


class FordFactory(AbstractCarFactory):
def create_product_car(self) -> AbstractProductCar:
    return Ford()

def create_product_engine(self) -> AbstractProductEngine:
    return FordEngine()

def create_product_wheel(self) -> AbstractProductWheel:
    return FordWheel()


class ToyotaFactory(AbstractCarFactory):
def create_product_car(self) -> AbstractProductCar:
    return Toyota()

def create_product_engine(self) -> AbstractProductEngine:
    return ToyotaEngine()

def create_product_wheel(self) -> AbstractProductWheel:
    return ToyotaWheel()


class MercedesFactory(AbstractCarFactory):
def create_product_car(self) -> AbstractProductCar:
    return Mercedes()

def create_product_engine(self) -> AbstractProductEngine:
    return MercedesEngine()

def create_product_wheel(self) -> AbstractProductWheel:
    return MercedesWheel()


class AbstractProductCar(ABC):
@abstractmethod
def info_car(self) -> str:
    pass

def interact1_car(self, collaborator: AbstractProductEngine) -> str:
    pass

def interact2_car(self, collaborator: AbstractProductWheel) -> str:
    pass


class AbstractProductEngine(ABC):
@abstractmethod
def get_power(self) -> str:
    pass


class FordEngine(AbstractProductEngine):
def get_power(self) -> str:
    return "Ford Engine"


class ToyotaEngine(AbstractProductEngine):
def get_power(self) -> str:
    return "Toyota Engine"


class MercedesEngine(AbstractProductEngine):
def get_power(self) -> str:
    return "Mercedes Engine"


class AbstractProductWheel(ABC):
@abstractmethod
def get_wheel(self) -> str:
    pass


class FordWheel(AbstractProductWheel):
def get_wheel(self) -> str:
    return "Ford Wheel"


class ToyotaWheel(AbstractProductWheel):
def get_wheel(self) -> str:
    return "Toyota Wheel"


class MercedesWheel(AbstractProductWheel):
def get_wheel(self) -> str:
    return "Mercedes Wheel"


class Ford(AbstractProductCar):
def info_car(self) -> str:
    return "Ford"

def interact1_car(self, collaborator: AbstractProductEngine) -> str:
    result1 = self.info_car() + " set Engine " + collaborator.get_power()
    return f"Result of setting engine to the body: ({result1})"

def interact2_car(self, collaborator: AbstractProductWheel) -> str:
    result2 = self.info_car() + " set Wheels " + collaborator.get_wheel()
    return f"Result of final assembly: {result2}"


class Toyota(AbstractProductCar):
def info_car(self) -> str:
    return "Toyota"

def interact1_car(self, collaborator: AbstractProductEngine) -> str:
    result1 = self.info_car() + " set Engine " + collaborator.get_power()
    return f"Result of setting engine to the body: ({result1})"

def interact2_car(self, collaborator: AbstractProductWheel) -> str:
    result2 = self.info_car() + "set Wheels " + collaborator.get_wheel()
    return f"Result of final assembly: {result2}"


class Mercedes(AbstractProductCar):
def info_car(self) -> str:
    return "Mercedes"

def interact1_car(self, collaborator: AbstractProductEngine) -> str:
    result1 = self.info_car() + " set Engine " + collaborator.get_power()
    return f"Result of setting engine to the body: ({result1})"

def interact2_car(self, collaborator: AbstractProductWheel) -> str:
    result2 = self.info_car() + "set Wheels " + collaborator.get_wheel()
    return f"Result of final assembly: {result2}"

def client_code(factory: AbstractCarFactory) -> None:
product_a = factory.create_product_car()
product_b = factory.create_product_engine()


print(f"{product_a.interact1_car(product_b)}"
     f"{product_a.interact2_car(product_b)}")


if __name__ == "__main__":
print("Client: Testing first factory:")
client_code(FordFactory())

print("Client: Testing second factory:")
client_code(ToyotaFactory())

print("Client: Testing third factory:")
client_code(MercedesFactory())

I've already tried to create abstract client code instead of copying it every time but it doesn't help. Even ChatGPT can't tell what's te matter lol

答案1

得分: 1

I'm providing the translated content:

我假设你发送的代码在复制和粘贴时缩进不正确,因为许多类的方法与类定义嵌套在一起。在修复后,我运行了你的代码并得到以下结果:

python3 test.py     
Client: Testing first factory:
NoneNone
Client: Testing second factory:
Traceback (most recent call last):
  File "/Users/jamied/git/pseudocode/test.py", line 157, in <module>
    client_code(ToyotaFactory())
  File "/Users/jamied/git/pseudocode/test.py", line 149, in client_code
    f"{product_a.interact2_car(product_b)}"
  File "/Users/jamied/git/pseudocode/test.py", line 127, in interact2_car
    result2 = self.info_car() + "set Wheels " + collaborator.get_wheel()
AttributeError: 'ToyotaEngine' object has no attribute 'get_wheel'

看起来你创建的第二个方法 interact2_car 似乎是要与 AbstractProductWheel 类交互,但你给它了一个 AbstractProductEngine 类。也许这才是你的本意?

def client_code(factory: AbstractCarFactory) -> None:
    product_a = factory.create_product_car()
    product_b = factory.create_product_engine()
    product_c = factory.create_product_wheel() # 我添加了这一行


    print(f"{product_a.interact1_car(product_b)}"
        f"{product_a.interact2_car(product_c)}") # 现在使用 product c

然后运行这段代码会得到以下结果:

python3 test.py
Client: Testing first factory:
Result of setting engine to the body: (Ford set Engine Ford Engine)Result of final assembly: Ford set Wheels Ford Wheel
Client: Testing second factory:
Result of setting engine to the body: (Toyota set Engine Toyota Engine)Result of final assembly: Toyotaset Wheels Toyota Wheel
Client: Testing third factory:
Result of setting engine to the body: (Mercedes set Engine Mercedes Engine)Result of final assembly: Mercedesset Wheels Mercedes Wheel

这希望是你想要的结果。

附注:通常在提问类似问题时附上错误消息会有助于更容易看到问题所在。

英文:

I'm assuming the code you've sent was indented incorrectly when copying and pasting as a lot of the methods for classes are inline with the class definition. After fixing that I ran your code and got:

python3 test.py     
Client: Testing first factory:
NoneNone
Client: Testing second factory:
Traceback (most recent call last):
  File &quot;/Users/jamied/git/pseudocode/test.py&quot;, line 157, in &lt;module&gt;
    client_code(ToyotaFactory())
  File &quot;/Users/jamied/git/pseudocode/test.py&quot;, line 149, in client_code
    f&quot;{product_a.interact2_car(product_b)}&quot;)
  File &quot;/Users/jamied/git/pseudocode/test.py&quot;, line 127, in interact2_car
    result2 = self.info_car() + &quot;set Wheels &quot; + collaborator.get_wheel()
AttributeError: &#39;ToyotaEngine&#39; object has no attribute &#39;get_wheel&#39;

It looks like the second method you created interact2_car was meant to interact with a AbstractProductWheel class but instead you gave it a AbstractProductEngine class. Maybe this is what you meant to do?

def client_code(factory: AbstractCarFactory) -&gt; None:
    product_a = factory.create_product_car()
    product_b = factory.create_product_engine()
    product_c = factory.create_product_wheel() # I added this


    print(f&quot;{product_a.interact1_car(product_b)}&quot;
        f&quot;{product_a.interact2_car(product_c)}&quot;) # now using product c

Then running this gives

python3 test.py
Client: Testing first factory:
Result of setting engine to the body: (Ford set Engine Ford Engine)Result of final assembly: Ford set Wheels Ford Wheel
Client: Testing second factory:
Result of setting engine to the body: (Toyota set Engine Toyota Engine)Result of final assembly: Toyotaset Wheels Toyota Wheel
Client: Testing third factory:
Result of setting engine to the body: (Mercedes set Engine Mercedes Engine)Result of final assembly: Mercedesset Wheels Mercedes Wheel

Which is hopefully what you wanted?

ps. it's usually helpful to post the error message when asking a question like this, it makes it easier to see what the problem is.

huangapple
  • 本文由 发表于 2023年5月13日 16:57:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/76241886.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定