Reputation: 3029
Currently I'm having a trouble with instantiating an AbstractFactory. There are some classes:
abstract class ABase { }
class A1 : ABase { }
class A2 : ABase { }
abstract class BBase { }
class B1 : BBase
{
private readonly A1 _a;
public B1(A1 a)
{
_a = a;
}
}
class B2 : BBase
{
private readonly A2 _a;
public B2(A2 a)
{
_a = a;
}
}
abstract class FactoryBBase
{
abstract public BBase Create(ABase b);
}
class FactoryB1 : FactoryBBase
{
override public BBase Create(ABase b)
{
return new B1(b as A1);
}
}
class FactoryB2 : FactoryBBase
{
override public BBase Create(ABase b)
{
return new B2(b as A2);
}
}
class Runtime
{
public void ProcessA(ABase a)
{
//How should I choose a proper factory?
}
}
How do I instantiate a proper abstract factory in ProcessA
method depending on the type of a
? The thing is that I don't want to have a big if/else block.
Upvotes: 2
Views: 111
Reputation: 1241
How to implement abstract factory really depends on what you need. What you have there is indeed a proper implementation, but I think it's not exactly what you need since you want to do something differently dependending on the type or state of an instance of ABase
.
The logic that analyses the type or state is exactly what I'd put into a factory.
abstract class ABase { }
class A1 : ABase { }
class A2 : ABase { }
public abstract class FactoryBBase
{
public abstract IProcessor Create(ABase a);
}
public class ConcreteFactory : FactoryBBase
{
override public IProcessor Create(ABase a)
{
// this is ugly for a large amount of ABase implementations of course
if (a is A1)
{
return new Runtime1();
}
if (a is A2)
{
return new Runtime2();
}
throw new NotSupportedException();
}
}
public interface IProcessor
{
void ProcessA(ABase a);
}
public class Runtime1 : IProcessor
{
public void ProcessA(ABase a)
{
// process away
}
}
public class Runtime2 : IProcessor
{
public void ProcessA(ABase a)
{
// process away differently
}
}
Multiple factory implementations come into play when you want the same type of ABase
implementation to be processed by different types of Runtime/Processor depending on state that is outside of ABase
.
Upvotes: 1
Reputation: 1116
You can use a lookup dictionary instead of a if-else/switch construct.
//classes used as markers
public interface IMarker {}
public class MarkerA : IMarker {}
public class MarkerB : IMarker {}
//classes to be created
public interface IData {}
public class DataA : IData {}
public class DataB : IData {}
//factory to call abstract factories (could use static here)
public class Factory
{
public IData Create(IMarker marker)
{
//lookup dictionary instead of if/switch
//func ensures instance is only created when required
var lookup = new Dictionary<Type, Func<DataFactoryBase>>()
{
{ typeof(MarkerA), () => new DataAFactory() },
{ typeof(MarkerB), () => new DataBFactory() },
};
//get factory by type and call constructor
return lookup[marker.GetType()]().Create();
}
}
//abstract factories
public abstract class DataFactoryBase
{
public abstract IData Create();
}
public class DataAFactory : DataFactoryBase
{
public override IData Create()
{
return new DataA();
}
}
public class DataBFactory : DataFactoryBase
{
public override IData Create()
{
return new DataB();
}
}
public static void Main()
{
//example will return DataA
IData data = new Factory().Create(new MarkerA());
}
Upvotes: 1
Reputation: 5916
how to instantiate a proper abstract factory in ProcessA method depending on the type of a?
To avoid big if/else block you can put all factories into a map, where key is the type of a
and value is the implementation. in Java I would do this either by Spring or I would create a static code, that can initialize the map when the class is loaded.
do I use AbstractFactory pattern as it is supposed to be uesd?
IMHO yes.
Upvotes: 1