C# class factory with subclasses - c#

I'm struggling to create a factory pattern where not the factory, but the classes determine which class needs to be used for creating the object. To make it more complicated than the normal factory pattern, the classes often need to create an instance of a subclass instead.
I would like to do something similar to this:
class Observation {
public int NumLegs;
public bool HasWings;
public NumChromosomes;
// etc.
}
class Organism {
public static Organism CreateByObservation(Observation obs) {
if (obs.numLegs == 4) return new Mammal.CreateByObservation(obs);
else if (obs.HasWings) return new Bird.CreateByObservation(obs);
// etc.
}
}
class Mammal: Organism {
public static override Mammal CreateByObservation(Observation obs) {
if (obs.NibblesALot) return new Rodent.CreateByObservation(obs);
else if (obs.Whinnies) return new Horse();
// etc.
}
}
class Rodent: Mammal {
public static override Rodent CreateByObservation(Observation obs) {
if (obs.Color == Colors.GRAY) return new Mouse();
else // ... you get the idea
}
}
// usage:
var myobservation = new Observation() { ... };
var myorganism = new Organism.CreateByObservation(myobservation);
tbName = myorganism.GetName();
For obvious reasons I'd like to encapsulate the determining code in the subclasses (Organism should know nothing about rodents), but since overriding static methods is not allowed in C# I can't use the above code.
What would be the best way to handle this?

You might consider separating your organism factories from your organisms data classes. This means you couple your factory to your data classes, but you don't couple your data classes to each other (apart from by inheritance).
For example:
//Organism objects
class Organism { ... }
class Mammal : Organism { ... }
class Rodent : Mammal { ... }
//Factory
class OrganismFactory
{
public static Organism CreateByObservation(Observation obs)
{
if (obs.numLegs == 4) return new Mammal.CreateByObservation(obs);
else if (obs.HasWings) return new Bird.CreateByObservation(obs);
// etc.
}
}

If your application grows you can look into Assembly Scanning. Basically you could create various classes that implement this interface, one single class per possible Organism subtype
interface IOrganismSubFactory
{
Organism Create(Observation observation);
}
For example one "sub" factory could look like this
class MammalFactory : IOrganismSubFactory
{
public Organism Create(Observation observation)
{
if (observation.NumLegs != 4) return null;
return new Mammal(obs);
}
}
Now to tie things together, you scan the assembly and get all possible subfactories and unite them in the factory like so
class OrganismFactory
{
IOrganismSubFactory[] _subFactories;
public OrganismFactory()
{
_subFactories = Assembly.GetCallingAssembly().GetTypes()
.Where(t => typeof(IOrganismSubFactory).IsAssignableFrom(t))
.Select(t => (IOrganismSubFactory)Activator.CreateInstance(t))
.ToArray();
}
public Organism Create(Observation observation)
{
return _subFactories.Select(factory => factory.Create(observation)).FirstOrDefault(instance => instance != null);
}
}
You can then use this Factory to create (well try to create) the instances
var factory = new OrganismFactory();
var organism = factory.Create(observation);
// organism is null if no factory was found
The reason why this might be a good idea is that you code is clearly separated, but you have to remember to create factories for each possible class.
One more advantage is that you could use a Dependency Injection library to wrap this logic and then enable you to use IoC. Basically this means that the subfactories could declare dependencies to other classes that get automatically injected into those subfactories.
This is probably beyond the scope of your current problem but still interesting to know

Related

How to implement the client code for an Abstract Factory?

I'm having a hard time understanding the implementation of client code with the factory method. I understand the overall use of Abstract Factories but my issue is I want the Factory to figure out the correct object to instantiate at runtime, but every implementation I see involves passing an enum or some other value to the constructor.
This is my current design
using System;
namespace FactoryTest.Jobs
{
public class ExchangeProvider1 : IExchangeProvider
{
public void Buy()
{
Console.WriteLine("Buying on Exchange1!");
}
}
}
using System;
namespace FactoryTest.Jobs
{
public class ExchangeProvider2 : IExchangeProvider
{
public void Buy()
{
Console.WriteLine("Buying on Exchange2");
}
}
}
public interface IExchangeFactory
{
}
public interface IExchangeProvider
{
void Buy();
}
public class ExchangeFactory : IExchangeFactory
{
public static IExchangeProvider CreateExchange<T>() where T : IExchangeProvider
{
return Activator.CreateInstance<T>();
}
public static IExchangeProvider CreateExchange(string exchangeName)
{
return (IExchangeProvider) Activator.CreateInstance<IExchangeProvider>();
}
}
The problem is that I'm trying to have the factory build the correct provider based on details the user fills out in a web form. On hitting create I want to the factory to instantiate the correct provider and run the correct logic. But with this implementation Im forced to do something like
var provider = ExchangeFactory.CreateExchange<Exchange1>();
When I really want to be able to get the Exchange Type from the user at runtime from the web form and pass it to the factory
//Receive IExchangeType from user submitting web form
var provider = ExchangeFactory.CreateExchange<IExchangeType>();
Is this possible? I'm wondering (or the correct solution), or if I'm on the right track but am definitely hindered by a gap in knowledge.
Generally you shouldn't tell the factory which concrete type to create. You should give it the information it needs to make that decision by itself. Now, I'm not saying that this can't be a 1:1 relationship, just that the caller shouldn't tell the factory to make a specific concrete type.
Imagine you have a Student object with a Grade property. You also have a factory which produces ISchool, and concrete implementations ElementarySchool, MiddleSchool, and HighSchool. Now you could have 3 methods: CreateElementarySchool(), CreateMiddleSchool() and CreateHighSchool(), but then the caller has to decide which one it wants.
A better approach is to have a method which uses some information to create the the school. For example: CreateSchoolForGrade(grade). Internally, the factory will have logic which works out which concrete type matches the grade.
In your case, if you have a set of 2 types to choose from on a webform, you could accept the type (let's say the options are Empire or Rebels). You could have an enum:
public enum Faction
{
Empire,
Rebels
}
and then a factory method:
public IFaction CreateFaction(Faction faction)
{
switch (faction)
{
case Faction.Empire:
return new EmpireFaction();
case Faction.Rebels:
return new RebelsFaction();
default:
throw new NotImplementedException();
}
}
Now, imagine that you retire EmpireFaction, replacing it with EmpireFactionV2. You only need to modify your factory, and the caller doesn't care:
public IFaction CreateFaction(Faction faction)
{
switch (faction)
{
case Faction.Empire:
return new EmpireFactionV2();
case Faction.Rebels:
return new RebelsFaction();
default:
throw new NotImplementedException();
}
}
As noted in the comments the other answer is a violation of O/C Principle (and a bit of Single Responsibility Principle (SRP)) of SOLID.
A more dynamic approach is to inject all instances of the exchange and pick the correct one. Bellow example is based on the class name (not full-qualifed name, but that cane easily be changed).
public interface IExchange
{
void Buy();
}
public class Exchange1 : IExchange
{
public void Buy() => Console.WriteLine("Buying on Exchange1");
}
public class Exchange2 : IExchange
{
public void Buy() => Console.WriteLine("Buying on Exchange2");
}
public interface IExchangeFactory
{
IExchange CreateExchange(string exchangeName);
}
// All exchanges are instantiated and injected
public class ExchangeFactory : IExchangeFactory
{
private readonly IEnumerable<IExchange> exchanges;
public ExchangeFactory(IEnumerable<IExchange> exchanges)
{
this.exchanges = exchanges ?? throw new ArgumentNullException(nameof(exchanges));
}
public IExchange CreateExchange(string exchangeName)
{
var exchange = exchanges.FirstOrDefault(e => e.GetType().Name == exchangeName);
if(exchange==null)
throw new ArgumentException($"No Exchange found for '{exchangeName}'.");
return exchange;
}
}
It can easily be extended by registering further implementation with the DI, w/o any code changes on the factory
service.AddScoped<IExchange, Exchange3>();
service.AddScoped<IExchange, Exchange4>();
In high performance scenarios (a couple of 1000 requests per second) where the injected services are scoped/transient or the memory/GC pressure on creating this extra instances is high, you can use the provider pattern to only create the exchange that's really required:
public interface IExchangeProvider
{
IExchange CreateExchange(string exchangeName);
}
public class Exchange1Provider : IExchangeProvider
{
public IExchange CreateExchange(string exchangeName)
{
if(exchangeName == nameof(Exchange1))
{
// new it, resolve it from DI, use activation whatever suits your need
return new Exchange1();
}
return null;
}
}
public class Exchange2Provider : IExchangeProvider
{
public IExchange CreateExchange(string exchangeName)
{
if (exchangeName == nameof(Exchange2))
{
// new it, resolve it from DI, use activation whatever suits your need
return new Exchange1();
}
return null;
}
}
public class LazyExchangeFactory : IExchangeFactory
{
private readonly IEnumerable<IExchangeProvider> exchangeProviders;
public LazyExchangeFactory(IEnumerable<IExchangeProvider> exchangeProviders)
{
this.exchangeProviders = exchangeProviders ?? throw new ArgumentNullException(nameof(exchangeProviders));
}
public IExchange CreateExchange(string exchangeName)
{
// This approach is lazy. The providers could be singletons etc. (avoids allocations)
// and new instance will only be created if the parameters are matching
foreach (IExchangeProvider provider in exchangeProviders)
{
IExchange exchange = provider.CreateExchange(exchangeName);
// if the provider couldn't find a matcing exchange, try next provider
if (exchange != null)
{
return exchange;
}
}
throw new ArgumentException($"No Exchange found for '{exchangeName}'.");
}
}
This approach is similar to the first, with the exception that you are extending it by adding new IExchangeProviders. Both approaches allow you to extend the exchanges w/o a change on ExchangeFactory (or in high performance scenarios LazyExchangeFactory)

Invoking a singleton class in a abstract factory method

I have a class with abstract factory method as follows:
public abstract class OpClass
{
public abstract IHou OperationInvoke(string opClass);
}
public class FactoryClass : OpClass
{
public override IHou OperationInvoke(string opClass)
{
if(opClass == "T")
{
//new Treasure();
}
}
}
and the concrete "Treasure" class goes like this:
public interface IHou
{
void Operation(Player p, List<Player> lstPlayers);
}
public sealed class Treasure : IHou
{
private static Treasure instance = null;
private static readonly object padlock = new object();
Treasure()
{
}
public static Treasure Instance
{
get
{
lock (padlock)
{
if (instance == null)
{
instance = new Treasure();
}
return instance;
}
}
}
public void Operation(Player p, List<Player> lstPlayers)
{
p.Points = p.Points + 200;
}
}
In my main Method I am trying to call it as:
Main()
{
Player p = //Populate from db;
List<Player> players = //populate from db
OpClass c = new FactoryClass();
IHou output = c.OperationInvoke("T");
output.Operation(p, players);
}
But the thing I need a single instance of "Treasure" class so I had the idea of changing the normal "Treasure" class to a singleton class.
So in this scenario how do I create a single instance of Treasure class and also preserve facory pattern? And if it's not possible to implement whats the best solution if the number of concrete classes get added like Treasure , House , Blocks etc.?
Edit : Is it not appropriate to use factory pattern here , as my understanding was if we have many classes with common behaviours like in this Treasure , and say one more class "House" gets added which calculates points in a different way , I will allow the factory to decide to invoke which one to instantiate.
you can make use of Flyweight pattern for this, in this pattern you will store instance in cache or dictionary and return it from the factory
with the help of generics based implementation of factory as below you dont need to add more cases , it will create class based on Template type T. you can visit article link below have same king of implemenration.
public class FlyWeidhtFactory
{
Dictionary<string,IHou> dic = new Dictionary<string,IHou>();
public IHou OperationInvoke<T>(string opClass) where T: IHou
{
Type type = typeof(T);
string fullname = type.FullName;
if(!dic.Contains(fullname)
{
Object obj = Activator.CreateInstance(type);
dic[fullname] = (T)obj;
//no need of more cases
}
return dic[opClass];
}
}
pattern ensure that you are going to create many objects, and by above implementation you are sure that only one instance of you class will get created. no need to go for singleton pattern.
Make your concrete class internal sealed, so it will not be visible outside you assembly.
Above is just suggestion based on your question.
Articles for factory and flyweight :
Flyweight Design Pattern
Factory Design Pattern With Generics
Just return the singleton instance in the factory.
Your factory has the responsibility of knowing how to 'make'. In the case of Treasure, there is only one instance, so the Factory just returns that.
The fact that you are returning shared or unshared instances based on a key makes your code similar to flyweight. If no other code needs to create Treasure outside the factory, then you do not need a Singleton. You can force the classes to be instantiated via the factory by making them nested classes of the factory.
So make Treasure a nested class of the factory with a private constructor. Or make it a private nested class and use the factory method to return an abstract base.

Ninject Contextual Binding at runtime depending on a specific value [duplicate]

If I have the following code:
public class RobotNavigationService : IRobotNavigationService {
public RobotNavigationService(IRobotFactory robotFactory) {
//...
}
}
public class RobotFactory : IRobotFactory {
public IRobot Create(string nameOfRobot) {
if (name == "Maximilian") {
return new KillerRobot();
} else {
return new StandardRobot();
}
}
}
My question is what is the proper way to do Inversion of Control here? I don't want to add the KillerRobot and StandardRobot concretes to the Factory class do I? And I don't want to bring them in via a IoC.Get<> right? bc that would be Service Location not true IoC right? Is there a better way to approach the problem of switching the concrete at runtime?
For your sample, you have a perfectly fine factory implementation and I wouldn't change anything.
However, I suspect that your KillerRobot and StandardRobot classes actually have dependencies of their own. I agree that you don't want to expose your IoC container to the RobotFactory.
One option is to use the ninject factory extension:
https://github.com/ninject/ninject.extensions.factory/wiki
It gives you two ways to inject factories - by interface, and by injecting a Func which returns an IRobot (or whatever).
Sample for interface based factory creation: https://github.com/ninject/ninject.extensions.factory/wiki/Factory-interface
Sample for func based: https://github.com/ninject/ninject.extensions.factory/wiki/Func
If you wanted, you could also do it by binding a func in your IoC Initialization code. Something like:
var factoryMethod = new Func<string, IRobot>(nameOfRobot =>
{
if (nameOfRobot == "Maximilian")
{
return _ninjectKernel.Get<KillerRobot>();
}
else
{
return _ninjectKernel.Get<StandardRobot>();
}
});
_ninjectKernel.Bind<Func<string, IRobot>>().ToConstant(factoryMethod);
Your navigation service could then look like:
public class RobotNavigationService
{
public RobotNavigationService(Func<string, IRobot> robotFactory)
{
var killer = robotFactory("Maximilian");
var standard = robotFactory("");
}
}
Of course, the problem with this approach is that you're writing factory methods right inside your IoC Initialization - perhaps not the best tradeoff...
The factory extension attempts to solve this by giving you several convention-based approaches - thus allowing you to retain normal DI chaining with the addition of context-sensitive dependencies.
The way you should do:
kernel.Bind<IRobot>().To<KillingRobot>("maximilliam");
kernel.Bind<IRobot>().To<StandardRobot>("standard");
kernel.Bind<IRobotFactory>().ToFactory();
public interface IRobotFactory
{
IRobot Create(string name);
}
But this way I think you lose the null name, so when calling IRobotFactory.Create you must ensure the correct name is sent via parameter.
When using ToFactory() in interface binding, all it does is create a proxy using Castle (or dynamic proxy) that receives an IResolutionRoot and calls the Get().
I don't want to add the KillerRobot and StandardRobot concretes to the Factory class do I?
I would suggest that you probably do. What would the purpose of a factory be if not to instantiate concrete objects? I think I can see where you're coming from - if IRobot describes a contract, shouldn't the injection container be responsible for creating it? Isn't that what containers are for?
Perhaps. However, returning concrete factories responsible for newing objects seems to be a pretty standard pattern in the IoC world. I don't think it's against the principle to have a concrete factory doing some actual work.
I was looking for a way to clean up a massive switch statement that returned a C# class to do some work (code smell here).
I didn't want to explicitly map each interface to its concrete implementation in the ninject module (essentially a mimic of lengthy switch case, but in a diff file) so I setup the module to bind all the interfaces automatically:
public class FactoryModule: NinjectModule
{
public override void Load()
{
Kernel.Bind(x => x.FromThisAssembly()
.IncludingNonPublicTypes()
.SelectAllClasses()
.InNamespaceOf<FactoryModule>()
.BindAllInterfaces()
.Configure(b => b.InSingletonScope()));
}
}
Then create the factory class, implementing the StandardKernal which will Get the specified interfaces and their implementations via a singleton instance using an IKernal:
public class CarFactoryKernel : StandardKernel, ICarFactoryKernel{
public static readonly ICarFactoryKernel _instance = new CarFactoryKernel();
public static ICarFactoryKernel Instance { get => _instance; }
private CarFactoryKernel()
{
var carFactoryModeule = new List<INinjectModule> { new FactoryModule() };
Load(carFactoryModeule);
}
public ICar GetCarFromFactory(string name)
{
var cars = this.GetAll<ICar>();
foreach (var car in cars)
{
if (car.CarModel == name)
{
return car;
}
}
return null;
}
}
public interface ICarFactoryKernel : IKernel
{
ICar GetCarFromFactory(string name);
}
Then your StandardKernel implementation can get at any interface by the identifier of you choice on the interface decorating your class.
e.g.:
public interface ICar
{
string CarModel { get; }
string Drive { get; }
string Reverse { get; }
}
public class Lamborghini : ICar
{
private string _carmodel;
public string CarModel { get => _carmodel; }
public string Drive => "Drive the Lamborghini forward!";
public string Reverse => "Drive the Lamborghini backward!";
public Lamborghini()
{
_carmodel = "Lamborghini";
}
}
Usage:
[Test]
public void TestDependencyInjection()
{
var ferrari = CarFactoryKernel.Instance.GetCarFromFactory("Ferrari");
Assert.That(ferrari, Is.Not.Null);
Assert.That(ferrari, Is.Not.Null.And.InstanceOf(typeof(Ferrari)));
Assert.AreEqual("Drive the Ferrari forward!", ferrari.Drive);
Assert.AreEqual("Drive the Ferrari backward!", ferrari.Reverse);
var lambo = CarFactoryKernel.Instance.GetCarFromFactory("Lamborghini");
Assert.That(lambo, Is.Not.Null);
Assert.That(lambo, Is.Not.Null.And.InstanceOf(typeof(Lamborghini)));
Assert.AreEqual("Drive the Lamborghini forward!", lambo.Drive);
Assert.AreEqual("Drive the Lamborghini backward!", lambo.Reverse);
}

Factory Interface Create Method with object Argument

I have a question about creating a factory interface with a create method that can cater for accepting different argument types depending on the implementation.
To give you a bit more background, I am using dependency in injection in a project, and require stateful objects to be generated at runtime - therefore I am injecting factories (rather than the objects themselves) to create these stateful objects. The problem I have come across is that, for some interfaces, the concrete implementations simply cannot have the same constructor argument types, and so the factories that create an instance of these interfaces require almost 'dynamic' arguments to be passed to the create method.
I have been going over this for a couple of days, and the following is the best solution I could come up with (namely, passing an object to the factory create method and casting it in the concrete implementation of the factory). I am really looking for feedback from people who have come across this scenario before, to hear what they came up with, and whether or not the solution I am proposing below is acceptable.
Apologies if this is missing any information, and many thanks in advance!
//
// Types...
//
interface IDataStore
{
List<string> GetItems();
}
public class XmlDataStore : IDataStore
{
public XmlDataStore(XmlDocument xmlDoc)
{
// Initialise from XML Document...
}
public List<string> GetItems()
{
// Get Items from XML Doc...
}
}
public class SQLDataStore : IDataStore
{
public SQLDataStore(SqlConnection conn)
{
// Initialise from SqlConnection...
}
public List<string> GetItems()
{
// Get Items from Database Doc...
}
}
//
// Factories...
//
interface IDataStoreFactory
{
IDataStore Create(object obj);
}
class XmlDataStoreFactory : IDataStore
{
IDataStore Create(object obj)
{
// Cast to XmlDocument
return new XmlDataStore((XmlDocument)obj);
}
}
class SQLDataStoreFactory : IDataStore
{
IDataStore Create(object obj)
{
// Cast to SqlConnection
return new SQLDataStore((SqlConnection)obj);
}
}
Based on this comment you need one factory which produces several types of IDataStore. You could accomplish by creating a open generic factory method in the singleton factory instance.
interface IDataStore<TStoreType>
{
void SetBaseType(TStoreType obj);
List<string> GetItems();
}
interface IDataStoreFactory
{
IDataStore<TStoreType> Create<TStoreType>(TStoreType obj)
}
class DataStoreFactory : IDataStoreFactory
{
public IDataStore<TStoreType> Create<TStoreType>(TStoreType obj)
{
if (obj.GetType() == typeof(SqlConnection))
{
var store = new SQLDataStore((SqlConnection)(Object)obj);
return (IDataStore<TStoreType>)store;
}
if (obj.GetType() == typeof(XmlDocument))
{ //... and so on }
}
}
class SQLDataStore : IDataStore<SqlConnection>
{
private readonly SqlConnection connection;
public SQLDataStore(SqlConnection connection)
{
this.connection = connection;
}
public List<string> GetItems() { return new List<string>(); }
}
You can use this factory like this:
var factory = new DataStoreFactory();
var sqlDatastore = factory.Create(new SqlConnection());
var xmlDatastore = factory.Create(new XmlDocument());
Your datastore factory would become a lot less complex if you would use a DI container. You could inject the container in the factory and retrieve your instances directly from the container, which would typically build your instances from bottom to top, including there own dependencies, lifetime management and so on. But be very carefull with this approach, it is the first step to using the service locator pattern which is an anti pattern
Not really sure if I understand your question correctly but to me it sounds a little odd to have factory instances which you use for the creation of your statefull objects as you call them.
To directly answer your question: generics are your solution. You rinterface becomes an open generic abstraction:
interface IDataStore<TStoreType>
{
List<string> GetItems();
}
interface IDataStoreFactory<TStoreType>
{
IDataStore<TStoreType> Create(TStoreType obj);
}
and your factory classes will look like this:
class XmlDataStoreFactory : IDataStoreFactory<XmlDocument>
{
IDataStore<XmlDocument> Create(XmlDocument document)
{
return new XmlDataStore(document);
}
}
class SQLDataStoreFactory : IDataStoreFactory<SqlConnection>
{
IDataStore<SqlConnection> Create(SqlConnection connection)
{
return new SQLDataStore(connection);
}
}
This will work, but from the examples you give I got the impression you're using factories throughout your codebase. Maybe I'm wrong on this point, but look at your design and minimize the number of factories. Needing a factory means mixing data with behaviour and this will always, eventually, get you into trouble.
For example, let's say you have some kind of service which adds the current user to a audit log when he logs in. This service offcourse needs the current user which is a typical example of runtime data (or contextual data). But instead of:
public class AuditLogService
{
public void AddApplicationSignIn(User user)
{
//... add user to some log
}
}
I know this is not a good example because you actually wouldn't need a factory for this class, but with the next code example you'll get the point:
public class AuditLogService
{
private readonly IUserContext userContext;
public AuditLogService(IUserContext userContext)
{
this.userContext = userContext;
}
public void AddApplicationSignIn()
{
var user = this.userContext.GetCurrentUser();
//... add user to some log
}
}
So by splitting data from behaviour you rule out the need for factories. And admitted there are cases where a factory is the best solution. I do think an IDataStore is not something you need a factory for.
For a good blog on splitting data and behaviour read here

Factory Pattern implementation without reflection

I am doing some research on design pattern implementation variants, i have come across and read some examples implemented here http://www.codeproject.com/Articles/37547/Exploring-Factory-Pattern and http://www.oodesign.com/factory-pattern.html. My focus of concern is when implementing factory pattern without reflection . the stated articles said that we need to register objects not classes which seems fine and logical to me but when seeing the implementation i see the duplication of objects e.g in the code below
// Factory pattern method to create the product
public IRoomType CreateProduct(RoomTypes Roomtype)
{
IRoomType room = null;
if (registeredProducts.Contains(Roomtype))
{
room = (IRoomType)registeredProducts[Roomtype];
room.createProduct();
}
if (room == null) { return room; }
else { return null; }
}
// implementation of concrete product
class NonACRoom : IRoomType
{
public static void RegisterProduct()
{
RoomFactory.Instance().RegisterProduct(new NonACRoom(), RoomTypes.NonAcRoom);
}
public void getDetails()
{
Console.WriteLine("I am an NON AC Room");
}
public IRoomType createProduct()
{
return new NonACRoom();
}
}
the method RegisterProduct is used for self registeration, we have to call it anyways before creating factory object i.e before some where in the main class of the client or anywhere applicable that ensure its calling. below is we are creating a new product and in the method above we are creating again a new product which seems non sense. any body comment on that
I have done something similar to this in the past. This is essentially what I came up with (and also doing away with the whole "Type" enumeration):
public interface ICreator
{
IPart Create();
}
public interface IPart
{
// Part interface methods
}
// a sample creator/part
public PositionPartCreator : ICreator
{
public IPart Create() { return new PositionPart(); }
}
public PositionPart : IPart
{
// implementation
}
Now we have the factory itself:
public sealed class PartFactory
{
private Dictionary<Type, IPartCreator> creators_ = new Dictionary<Type, IPartCreator>();
// registration (note, we use the type system!)
public void RegisterCreator<T>(IPartCreator creator) where T : IPart
{
creators_[typeof(T)] = creator;
}
public T CreatePart<T>() where T: IPart
{
if(creators_.ContainsKey(typeof(T))
return creators_[typeof(T)].Create();
return default(T);
}
}
This essentially does away with the need for a "type" enumeration, and makes things really easy to work with:
PartFactory factory = new PartFactory();
factory.RegisterCreator<PositionPart>(new PositionPartCreator());
// all your other registrations
// ... later
IPart p = factory.CreatePart<PositionPart>();
The first creation is used to give something to work on to RegisterProduct. Probably, the cost of that object is neglectable. It's done during initialization and won't matter much.
This instance is required though because in C# you need an object to call createProduct on. This is because you can't use reflection to store a reference to a type instead of a reference to an object.

Categories

Resources