C #: abstract base strategy class used as Factory object for strategy objects

I am trying to create a web tool for my company, which, in fact, uses a geographical input to obtain tabular results. Currently, three different business areas use my tool and get three different types of products. Fortunately, all outputs are based on the same idea of ​​the Master Table - Child Table, and they even share a common table.

Unfortunately, in each case, the related rows in the Child table contain significantly different data. Since this is the only point of competition, I extracted the method FetchChildDatainto a separate class called DetailFinder. As a result, my code is as follows:

DetailFinder DetailHandler;
if (ReportType == "Planning")
  DetailHandler = new PlanningFinder();
else if (ReportType == "Operations")
  DetailHandler = new OperationsFinder();
else if (ReportType == "Maintenance")
  DetailHandler = new MaintenanceFinder();
DataTable ChildTable = DetailHandler.FetchChildData(Master);

Where PlanningFinder, OperationsFinder, and MaintenanceFinder are all subclasses of DetailFinder.

I was simply asked to add support for another area of ​​the business and would not like to continue this block trend if. I would prefer to have a parse method that looks like this:

DetailFinder DetailHandler = DetailFinder.Parse(ReportType);

However, I find it difficult to DetailFinderknow which subclass processes each line, or even which subclasses exist, without changing only the if block to a method Parse. Is there a way for subclasses to register with abstract DetailFinder?

+3
source share
6 answers

You might want to use a type map for creation methods:

public class  DetailFinder
{
    private static Dictionary<string,Func<DetailFinder>> Creators;

    static DetailFinder()
    {
         Creators = new Dictionary<string,Func<DetailFinder>>();
         Creators.Add( "Planning", CreatePlanningFinder );
         Creators.Add( "Operations", CreateOperationsFinder );
         ...
    }

    public static DetailFinder Create( string type )
    {
         return Creators[type].Invoke();
    }

    private static DetailFinder CreatePlanningFinder()
    {
        return new PlanningFinder();
    }

    private static DetailFinder CreateOperationsFinder()
    {
        return new OperationsFinder();
    }

    ...

}

Used as:

DetailFinder detailHandler = DetailFinder.Create( ReportType );

, , if, . Creators.

, Activator.CreateInstance , . factory, , , .

public class DetailFinder
{
      private static Dictionary<string,Type> Creators;

      static DetailFinder()
      {
           Creators = new Dictionary<string,Type>();
           Creators.Add( "Planning", typeof(PlanningFinder) );
           ...
      }

      public static DetailFinder Create( string type )
      {
           Type t = Creators[type];
           return Activator.CreateInstance(t) as DetailFinder;
      }
}
+1

IoC, .

, IoC :

IoC.Register<DetailHandler, PlanningFinder>("Planning");
IoC.Register<DetailHandler, OperationsFinder>("Operations");
...

:

DetailHandler handler = IoC.Resolve<DetailHandler>("Planning");

.

IoC:

+3

if switch , , , .

, , -. , DetailFinders , Managed Extensibility Framework, "add-ins" , DetailFinders.

, , .

0

- if..else, , , factory.

factory hashmap (). / , .

- , . , , . , ;)

0

. Parse DetailFinder ( ):

public DetailFinder Parse(ReportType reportType)
{
    string detailFinderClassName = GetDetailFinderClassNameByReportType(reportType);
    return Activator.CreateInstance(Type.GetType(detailFinderClassName)) as DetailFinder;
}

GetDetailFinderClassNameByReportType , ..

, "Plugin" : P EAA:

0

, if/switch , ( , - ).

However, I would probably just use polymorphism (so that the type system works for me). Ask each report to implement the FindDetails method (I would inherit them from the abstract Report class), since you will end up with several types of detail search anyway. It also models pattern matching and algebraic data types from functional languages.

0
source

Source: https://habr.com/ru/post/1727293/


All Articles