From grimoire
Applies the Factory Method pattern to delegate object creation to subclasses or configuration, reducing coupling and enabling extensibility.
How this skill is triggered — by the user, by Claude, or both
Slash command
/grimoire:apply-factory-method-patternThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Define an interface for creating an object, but let subclasses decide which class to instantiate.
Define an interface for creating an object, but let subclasses decide which class to instantiate.
Adopted by: Java's Collection.iterator() (the most-called factory method in the
Java standard library), JDBC DriverManager.getConnection(), Python's
logging.getLogger(), Django ORM model managers, and Spring BeanFactory — all of
which allow callers to receive a product without knowing its concrete type.
Impact: GoF documents that Factory Method eliminates the coupling between
application-specific classes and the objects they must create. Django's model manager
factory is one of the most-cited examples of the pattern enabling framework
extensibility: users override the factory to return custom QuerySet subclasses without
modifying the ORM.
Why best: The alternative — new ConcreteProduct() at every call site — couples the
caller to the specific class. When the concrete type must change (new database driver,
new log handler, new collection type), every call site changes. Factory Method
centralizes that coupling in one overridable method.
Sources: Gamma et al. (1994) pp. 107–116; JDBC API specification; Django ORM documentation (Manager class)
from abc import ABC, abstractmethod
class Notification(ABC):
@abstractmethod
def send(self, message: str) -> None: ...
class NotificationService(ABC):
@abstractmethod
def create_notification(self) -> Notification:
"""Factory method — subclasses override this."""
...
def notify(self, message: str) -> None:
notification = self.create_notification() # calls factory method
notification.send(message)
class EmailNotificationService(NotificationService):
def create_notification(self) -> Notification:
return EmailNotification()
class SMSNotificationService(NotificationService):
def create_notification(self) -> Notification:
return SMSNotification()
The notify() method in Step 2 works identically regardless of which
create_notification() returns. That independence is the pattern's value — the creator
algorithm is reusable across all product variants.
When subclassing is unnecessary, use a parameterized factory method:
class NotificationFactory:
@staticmethod
def create(channel: str) -> Notification:
match channel:
case "email": return EmailNotification()
case "sms": return SMSNotification()
case _: raise ValueError(f"unknown channel: {channel}")
This variant is simpler than the full GoF structure when the creator hierarchy is not needed.
apply-abstract-factory-pattern instead.new Product() is cleaner. Factory Method adds a layer only when variation is the point.__init__ with keyword arguments and type hints is often cleaner than a one-off factory for simple objects.Naming the factory method create() — generic names lose the domain signal. Name it for the product: create_notification(), create_connection(), build_query().
Putting business logic inside the factory method — the factory method should only instantiate. Initialization or validation belongs in the product's __init__, not the factory.
Forgetting to parameterize when subclassing is unnecessary — the static variant (Step 5) is valid and often simpler. Don't force a class hierarchy when a single parameterized method suffices.
npx claudepluginhub jeffreytse/grimoire --plugin grimoireCentralizes object creation for families of related objects, enabling easy swapping of product families without client code changes. Based on the GoF pattern.
Provides TypeScript implementations of the Factory Method pattern, including class-based, function-based, and generic registry approaches. Useful for decoupling object creation from client code.
Applies Python design principles like KISS, SRP, composition over inheritance, and Rule of Three for designing services, refactoring monoliths, reducing coupling, and improving testability.