I am trying to apply a creation pattern to the following business domain. I am not sure if it is the right solution but I have been looking at the factory and builder pattern but I might be trying to apply the wrong pattern. Here is the following domain:
So above I have a business objects of technical specifications, I am just showing an example of two but they could be up to N objects. This holds true for the properties of the technical specifications, there could up to N properties for each specification.
I am running into roadblocks trying to code this in an abstract way using the patterns mentioned above if I want to return back the properties of the technical specifications. I am forced to cast them, any advice on a pattern that would be applicable in this case?
Here is some code sample of what I am trying to do, please see below. In the main function I can build my specification objects but if I want to access the concrete properties of the Specification Object without casting. I hope this clarify some things.
Main Function:
class Program
{
static void Main(string[] args)
{
TechnicalSpecificationBuilder visual = new VisualSpecificationBuilder();
TechnicalSpecificationBuilder audio = new AuditorySpecificationBuilder();
//TODO, how do I get acces to properties without Casting?
Specification visualSpec = visual.CreateSpecification();
Specification audiotSpec = audio.CreateSpecification();
}
}
Abstract Tech Spec Builder:
public abstract class TechnicalSpecificationBuilder
{
public Specification CreateSpecification()
{
return BuildSpecification();
}
protected abstract Specification BuildSpecification();
}
Visual Tech Spec Builder:
public class VisualSpecificationBuilder : TechnicalSpecificationBuilder
{
protected override Specification BuildSpecification()
{
// TODO: Implement this method
return new VisualSpecification();
}
}
Abstract Specification:
public abstract class Specification
{
}
Visual Specification:
public class VisualSpecification : Specification
{
public string FieldOfView { get; set; }
public bool IsBinocularVisionCapable { get; set; }
public bool IsHeadTrackingCapable { get; set; }
public bool IsEyeTrackingCapable { get; set; }
public string Resolution { get; set; }
}
The following should do the trick - use a generic base class for the builder classes and make the concrete specification subclass a type parameter.
public abstract class TechnicalSpecificationBuilder<TSpecification>
where TSpecification : Specification
{
public TSpecification CreateSpecification()
{
return this.BuildSpecification();
}
protected abstract TSpecification BuildSpecification();
}
public class VisualSpecificationBuilder : TechnicalSpecificationBuilder<VisualSpecification>
{
protected override VisualSpecification BuildSpecification()
{
return new VisualSpecification();
}
}
I also suggest to think about using an interface ISpecification
instead or together with you base class Specification
- this could help if you reach a point where a concrete specification class can not derive from you base class for whatever reasons.