jeudi 26 mars 2020

How to make one class execute multiple sub-classes which have the same template?

I have the following code design with two classes with the same methods, like this:

class Worker1:
    def __init__(self, tools=None):
        if tools is None:
            self.tools = self._get_tools()
        else:
            self.tools = tools

    def _get_tools(self):
        return ['hammer', 'nails']

    def do_work(self):
        return 1 * len(self.tools)


class Worker2:
    def __init__(self, tools=None):
        if tools is None:
            self.tools = self._get_tools()
        else:
            self.tools = tools

    def _get_tools(self):
        return ['car', 'gas']

    def do_work(self):
        return 2 * len(self.tools)

Note that:

  • both classes have the same methods inside
  • both classes have the same initialization code

Now I want to have one Master Class which can perform operations on the Worker classes. What I currently have is:

class Manager:
    def __init__(self):
        self._worker_map = {}
        self.worker_names = self._worker_map.keys()

    def register_worker(self, worker_name, worker):
        self._worker_map[worker_name] = worker

    def do_work(self, worker_names=None):
        if worker_names is None:
            worker_names = self.worker_names
        return {worker_name: self._worker_map[worker_name].do_work()
                for worker_name in self.worker_names}

# I initialize the Manager class in my module and register all the workers one by one.
manager = Manager()
manager.register_worker('Joe', Worker1())
manager.register_worker('Ben', Worker2())

This works fine for me, in the sense that I can use the manager to operate all the register workers and get information from all of them; for example:

manager.do_work() # returns a dict with keys as worker's name and values as output

, however the big issue I have here is that it only works if I don't have any input when I initialize the workers... If I want to initialize each worker with the same set of tools, that's now not possible.

My question is: How can I have a Manager class to control my workers, when I want to give each worker the same set of tools?

I guess that then I will have to somehow have all workers already register in the manager, but the manager needs to be initialized at runtime, such that I can pass to the manager the tools I want each worker to have, before the workers are initialized... but since I initialize on registration, this is currently not possible. I hope my question / example is not too confusing. I did my best to simplify as much as possible.

P.S. I was reading up on the Factory design patter, but could not truly see whether it fits my desired use case here.

Update

I think by writing this I figured it out. If I write my Manager class like so, then I can initialize it with or without the tools. However, is this a good design at all?

class Manager:
    def __init__(self, tools=None):
        self._worker_map = {
            'Joe': Worker1(tools=tools),
            'Ben': Worker2(tools=tools)
        }
        self.worker_names = self._worker_map.keys()

    def do_work(self, worker_names=None):
        if worker_names is None:
            worker_names = self.worker_names
        return {worker_name: self._worker_map[worker_name].do_work()
                for worker_name in self.worker_names}

Aucun commentaire:

Enregistrer un commentaire