简体   繁体   中英

Is there a design pattern for accessing concrete types in an IEnumerable<IFoo>?

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:

  • Technical Specifications
    • Visual Specs
      • Field of View (String)
      • Resolution (String)
    • Audio Specs
      • Frequency Range (String)
      • Microphone (boolean)

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM