5

Let me introduce my problem. I am creating a set of objects which are generally Food, but each of them might have completely different set of attributes to set. I thought to use Factory design pattern, then i faced a problem where and how to set objects attributes and then i found some Builder pattern. However i am not sure if i am at the right path. Example:

class Food(object):
    def __init__(self, taste = None):
        self._taste = taste
class Bread(Food):
   def __init__(self, flour_type = None):
       Food.__init__(self, taste = 'good')
       self._flour = flour_type
class Meat(Food):
   def __init__(self, type = None, energy_value = None, taste = None):
       Food.__init__(self, taste = taste)
       self._type = type
       self._energy = energy_value
class Soup(Food):
   def __init__(self, name = None, recipe = None):
       Food.__init__(self, taste = 'fine')
       self._name = name
       self._recipe = recipe

and then i have a factory like this:

FOOD_TYPES = {'food':Food, 'bread':Bread, 'meat':Meat, 'soup':Soup}

class FoodFactory(object):
    @staticmethod
    def create_food(food_type):
        try:
            return FOOD_TYPES[food_type.lower()]()
        except Exception:
            return None

My question is: I want to pass parameters for constructors but dont know how. Is Builder pattern good idea here or not? The list of attributes might be longer. I was also wondering if passing a context dictionary with attribute name as a key and value as value. Any ideas how to solve this? Really appreciate any hints and tips.

Regards

3
  • 2
    This looks overengineered to me. What does FoodFactory earn you? What does storing the classes in a dictionary and dispatching on a string earn you? Commented Mar 10, 2016 at 12:46
  • 1
    When you create a Food subclass instance, you obviously know which one you're creating because of the food_type argument that FoodFactory.create_food() requires...and presumably also what its attributes are or should be. Just call the subclass directly and pass the argument values needed to construct it. That said, to make what you have be able to pass arbitrary arguments, you could make the create_food() method accept **kwargs and pass them on to the called class pulled from the dictionary. Commented Mar 10, 2016 at 13:03
  • @BenjaminHodgson the dictionary works as a switch statement but it could be also written with if and elifs. At the moment i ve got one big file parsing some response and i want to make it maintainable and much more cleaner. That is why i thought about making Food Factory. Commented Mar 10, 2016 at 13:32

1 Answer 1

8

Just edit your FoodFactory like this:

class FoodFactory(object):
    @staticmethod
    def create_food(food_type, **kwargs):
        try:
            return FOOD_TYPES[food_type.lower()](**kwargs)
        except Exception:
            return None

Now you can use keyworded arguments for each Food class:

>>> meat = FoodFactory.create_food("meat", energy_value=25)
>>> print meat
>>> print meat._energy

Will print out something like:

>>> <__main__.Meat object at 0x03122AB0>
>>> 25

Hope this helps!

Sign up to request clarification or add additional context in comments.

1 Comment

you are losing a lot of typing information if you implement it like this though

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.