From f7355270c8b2ce6ef18d493d4b74e65ace47b5dd Mon Sep 17 00:00:00 2001 From: Jens Ahrensfeld Date: Thu, 25 Jun 2026 20:44:43 +0200 Subject: [PATCH] Extract shared factory dispatch into ComponentFactory base class All four name-dispatch factories repeated the same if/elif lazy-import pattern. Replace with a ComponentFactory base class holding a callable registry and a _lazy() helper for the common import-and-construct case. PlantFactory is an orchestrator, not a dispatcher, and is left as-is. Co-Authored-By: Claude Sonnet 4.6 Claude-Session: https://claude.ai/code/session_01Tqxrk8uj4M3w3d3eXm3xK8 --- components/actor/heaterFactory.py | 15 ++++++--------- components/actor/stirrerFactory.py | 20 +++++++++++--------- components/factory.py | 19 +++++++++++++++++++ components/pid/pid_factory.py | 15 ++++++--------- components/sensor/tempsensor_factory.py | 15 ++++++--------- 5 files changed, 48 insertions(+), 36 deletions(-) create mode 100644 components/factory.py diff --git a/components/actor/heaterFactory.py b/components/actor/heaterFactory.py index cbaa4b8..59d0521 100644 --- a/components/actor/heaterFactory.py +++ b/components/actor/heaterFactory.py @@ -1,11 +1,8 @@ +from components.factory import ComponentFactory, _lazy -class HeaterFactory: - @staticmethod - def create(name, *args, **kwargs): - if "sim" in name: - from components.actor.heater_sim import HeaterSim - return HeaterSim(*args, **kwargs) - elif "Hendi" in name: - from components.actor.heater_hendi import HeaterHendi - return HeaterHendi(*args, **kwargs) +class HeaterFactory(ComponentFactory): + _registry = { + "sim": _lazy("components.actor.heater_sim", "HeaterSim"), + "Hendi": _lazy("components.actor.heater_hendi", "HeaterHendi"), + } diff --git a/components/actor/stirrerFactory.py b/components/actor/stirrerFactory.py index ecc9818..1aaad7a 100644 --- a/components/actor/stirrerFactory.py +++ b/components/actor/stirrerFactory.py @@ -1,11 +1,13 @@ +from components.factory import ComponentFactory, _lazy -class StirrerFactory: - @staticmethod - def create(name, dt, params): - if "sim" in name: - from components.actor.stirrersim import StirrerSim - return StirrerSim(dt) - elif "1376" in name: - from components.actor.stirrerpololu1376 import StirrerPololu1376 - return StirrerPololu1376(dt, params) +def _sim(dt, params): + from components.actor.stirrersim import StirrerSim + return StirrerSim(dt) + + +class StirrerFactory(ComponentFactory): + _registry = { + "sim": _sim, + "1376": _lazy("components.actor.stirrerpololu1376", "StirrerPololu1376"), + } diff --git a/components/factory.py b/components/factory.py new file mode 100644 index 0000000..e80d6be --- /dev/null +++ b/components/factory.py @@ -0,0 +1,19 @@ +import importlib + + +def _lazy(module, classname): + """Return a builder that lazily imports module.classname on first call.""" + def build(*args, **kwargs): + return getattr(importlib.import_module(module), classname)(*args, **kwargs) + return build + + +class ComponentFactory: + _registry = {} + + @classmethod + def create(cls, name, *args, **kwargs): + for key, builder in cls._registry.items(): + if key in name: + return builder(*args, **kwargs) + raise ValueError(f"{cls.__name__}: unknown name {name!r}") diff --git a/components/pid/pid_factory.py b/components/pid/pid_factory.py index d49ef6f..43963db 100644 --- a/components/pid/pid_factory.py +++ b/components/pid/pid_factory.py @@ -1,11 +1,8 @@ +from components.factory import ComponentFactory, _lazy -class PidFactory: - @staticmethod - def create(name, *args, **kwargs): - if "Normal" in name: - from components.pid.temp_controller import TempController - return TempController(*args, **kwargs) - elif "Smith" in name: - from components.pid.temp_controller_smith import TempController - return TempController(*args, **kwargs) +class PidFactory(ComponentFactory): + _registry = { + "Normal": _lazy("components.pid.temp_controller", "TempController"), + "Smith": _lazy("components.pid.temp_controller_smith", "TempController"), + } diff --git a/components/sensor/tempsensor_factory.py b/components/sensor/tempsensor_factory.py index dc7aa71..af065fb 100644 --- a/components/sensor/tempsensor_factory.py +++ b/components/sensor/tempsensor_factory.py @@ -1,11 +1,8 @@ +from components.factory import ComponentFactory, _lazy -class TempSensorFactory: - @staticmethod - def create(name, *args, **kwargs): - if "sim" in name: - from components.sensor.tempSensorSim import TempSensorSim - return TempSensorSim(*args, **kwargs) - elif "31865" in name: - from components.sensor.tempSensor_max31865 import TempSensor_max31865 - return TempSensor_max31865(*args, **kwargs) +class TempSensorFactory(ComponentFactory): + _registry = { + "sim": _lazy("components.sensor.tempSensorSim", "TempSensorSim"), + "31865": _lazy("components.sensor.tempSensor_max31865", "TempSensor_max31865"), + }