Abstract
When the design requires an "Abstract Factory Pattern" like stated by the [GoF] including several products and over some product families, then setting up an IoC can become a bit tricky. Especially when the specific factory implementations need to be dispatched by runtime parameters and shared among some subsequent components.
Given the follwing API, i was trying to set up my IoC (Ninject in this case) to retrieve Configuration
objects configured through a IConfigurationFactory
. The configuration stores an IFactory
instance whoose implementation is determined by a runtime parameter of type ProductFamily
. Afterwards the product types created by the factory inside of the configuration should always match the requested ProductFamily
. The subgraph, consisting of the Component
class holds the same IFactory
per Configuration
.
public enum ProductFamily { A, B }
public interface IProduct1 { }
public interface IProduct2 { }
public interface IFactory
{
IProduct1 CreateProduct1();
IProduct2 CreateProduct2();
}
public class Configuration
{
public readonly IFactory factory;
public readonly Component component;
public Configuration(IFactory factory, Component component)
{
this.factory = factory;
this.component = component;
}
}
public class Component
{
public IFactory factory;
public Component(IFactory factory) { this.factory = factory; }
}
public interface IConfigurationFactory
{
Configuration CreateConfiguration(ProductFamily family);
}
Tests
To clarify the intended behaviour i have added my test code writte in vstest. But forehand some additions, thanks to @BatterBackupUnit for asking these nitty details:
- The factories do only need the
ProductFamily
as a parameter to choose between the implementations, nothing else - Every
Configuration
and its subsequent objects like theComponent
, share the same factory instance
So i hope this helps :)
[TestMethod]
public void TestMethod1()
{
var configFac = ComposeConfigurationFactory();
// create runtime dependent configs
var configA = configFac.CreateConfiguration(ProductFamily.A);
var configB = configFac.CreateConfiguration(ProductFamily.B);
// check the configuration of the factories
Assert.IsInstanceOfType(configA.factory.CreateProduct1(), typeof(Product1A));
Assert.IsInstanceOfType(configB.factory.CreateProduct1(), typeof(Product1B));
Assert.IsInstanceOfType(configA.factory.CreateProduct2(), typeof(Product2A));
Assert.IsInstanceOfType(configB.factory.CreateProduct2(), typeof(Product2B));
// all possible children of the configuration should share the same factory
Assert.IsTrue(configA.factory == configA.component.factory);
// different configurations should never share the same factory
var configA2 = configFac.CreateConfiguration(ProductFamily.A);
Assert.IsTrue(configA.factory != configA2.factory);
}
This qestion has already been solved therefore i removed all the unnecessary fluff.
Thanks to @BatteryBackupUnit for your time and effort Best regards
Isaias