The abstract factory pattern is a common fixture of well designed code. As useful as it is, it can be an annoying pattern because the scaffolding to implementation ratio is quite high. It also breaks up code that most of the time should be together. Other patterns that reach this level of usage often benefit from being baked into the language framework, so why not this pattern.
Let's look at a fairly basic implementation:
public interface ButtonFactory
{
Button CreateButton();
Button CreateButton(Control parent);
}
public interface Button
{
void Draw();
}
public class WinButtonFactory : ButtonFactory
{
public Button CreateButton() { return new WinButton(); }
public Button CreateButton(Control parent) { return new WinButton(parent); }
}
public class WinButton : Button
{
internal WinButton() { ... implementation ... }
internal WinButton() { ... implementation ... }
public void Draw() { ... implementation ... }
}
public class SampleUser
{
public void UseFactory()
{
ButtonFactory factory = new WinButtonFactory();
Button parent = factory.Create();
Button child = factory.Create(parent);
}
}
This is okay, but if we had a little syntax help:
public interface Button
{
Button();
Button(Control parent);
void Draw();
}
public class WinButton : Button
{
public WinButton() { ... implementation ... }
public WinButton() { ... implementation ... }
public void Draw() { ... implementation ... }
}
public class SampleUser
{
public void UseFactory()
{
Factory<Button> factory = WinButton.GetFactory<Button>();
Button parent = factory;
Button child = factory(parent);
}
}
That's a fair bit more succinct, and it also allows the definition of the "Create" to reside within the interface, making it much more obvious to consumers of the API the relationship between the factory and the interface. The same is true for the implementation, where it's no longer necessary to either provide a workaround to the visibility issues that arise from having object initialization in a separate class.
Some might object on the basis that the use of the factory pattern extends beyond the example above, but those uses can still be accommodated:
public class ColoredButtonFactory : Factory<Button>
{
private Color _color;
private Factory<Button> _factory;
public ColoredButtonFactory(Color color, ButtonFactory factory);
{
_color = color;
_factory = factory;
}
public Button()
{
Button button = _factory();
button.Color = _color;
return button;
}
}
Which is equivalent to this implementation without language level factory support:
public class ColoredButtonFactory : ButtonFactory
{
private Color _color;
private ButtonFactory _factory;
public ColoredButtonFactory(Color color, ButtonFactory factory);
{
_color = color;
_factory = factory;
}
public Button CreateButton()
{
Button button = factory.CreateButton();
button.Color = _color;
return button;
}
}
An alternative (with pluses and minuses) the language level factory support would allow for is:
public class ColoredButtonFactory<TButton> : Factory<TButton>
where TButton : Button
{
private Color _color;
public ColoredButtonFactory(Color color);
{
_color = color;
}
public TButton()
{
TButton button = new TButton();
button.Color = _color;
return button;
}
}