Talk:Factory
From APIDesign
I prefer to use a factory reference type instead of a static factory method. This approach enables polymorphism for the factory result type and a corresponding polymorphism of the factory reference type.
Example:
public enum BankAccountEnum { CHECKING_ACCOUNT, SAVINGS_ACCOUNT; } public abstract class BankAccount { public abstract BankAccountEnum getBankAccountEnum(); public abstract BankAccountFactory getBankAccountFactory(); } public abstract class BankAccountFactory { public abstract BankAccount createBankAccount(); }
Each result instance carries with it a reference to the factory instance that created it. I can directly get the correct factory instance to create a clone.
The BankAccount base class can be polymorphically subclassed into SavingsAccount and CheckingAccount, with corresponding subclasses for SavingsAccountFactory and CheckingAccountFactory.
public abstract class CheckingAccount extends BankAccount { public final BankAccountEnum getBankAccountEnum() { return BankAccountEnum.CHECKING_ACCOUNT; } public abstract CheckingAccountFactory getCheckingAccountFactory(); public final BankAccountFactory getBankAccountFactory() { return getCheckingAccountFactory(); } } public abstract class CheckingAccountFactory extends BankAccountFactory { public abstract CheckingAccount createCheckingAccount(); public final BankAccount createBankAccount() { return createCheckingAccount(); } }
and a similar pair of classes for SavingsAccount. I can keep the factory instances in an array that is indexed by the BankAccountEnum to select the factory that matches the kind of account that I want to create. Or I can wrap the array within a "Factories" class that has methods for obtaining the factory instance or directly creating an instance from a specified BankAccountEnum.
public abstract class BankAccountFactories { public abstract BankAccountFactory getBankAccountFactory(BankAccountEnum theBankAccountEnum); public final BankAccount createBankAccount(BankAccountEnum theBankAccountEnum) { BankAccount result; BankAccountFactory factory; factory = getBankAccountFactory(theBankAccountEnum); result = factory.createBankAccount(); return result; } }
The "Factories" instance can be implemented elsewhere and saved in a global repository for any component to use without knowing anything about the underlying implementation. The use of enum indeces allows for easily extending the polymorphism to future subclasses (e.g., MoneyMarketAccount) without affecting existing clients.
Of course, I use an automated code generator to create the Java source code, so it's easy for me to maintain consistent source code structure throughout the polymorphic pieces.
Two cents worth. Your mileage may vary.