简体   繁体   中英

How to create complex objects using factory design pattern

Hello i have to create a complex object, and i wanted to use the factory pattern for it.However i do not know what to do with the additional dependencies that the object needs in order to be created.

Dependencies

public class SomeService
{
}
public class SomeOtherService
{
}

Hierarchy

public abstract class NeededObjectBase
{
  public readonly int Type {get;set;}  //id selected by the factory

  public abstract void DoSomething();
}
public class A:NeededObjectBase
{
   private SomeService service;
   A(SomeService service){ this.service=service;}
   public override void DoSomething(){}
}
public class B:NeededObjectBase
{
   public B(SomeService service,SomeOtherService otherService){
       this.service=service;
       this.otherService=otherService
   }
   public SomeOtherService service;
   public SomeOtherService otherService;
   public override void DoSomething(){}
}

Factory

public class Factory
{
   public static NeededObjectBase CreateInstance(int type)
   {
       switch(type)
       {
        case 0:return new A();  //this would need SomeService => new A(someService)
        case 1:return new B();   // this would need SomeService & SomeOtherService => new B(someService,someOtherService);
        default: return new A();
       }
   }
}

Usage

public class Aggregate
{
   private SomeService s1;
   private SomeOtherService s2;
   public void UseNeededObject(int type)
   {
     NeededObjectBase neededObject=Factory.CreateInstance(type);
     neededObject.DoSomething();
   }
}

If you look in the code things happen like this:
I have an Aggregate class where i keep my dependencies .
Inside its method i use the Factory based on the type parameter in order to create the right object.
However i do not know what to do with the dependencies.Should the factory get all the required dependencies in order to create the objects?

So basically i do not know who should keep the dependencies for object creation.The factory makes the selection but how does it provide the right dependencies in order to instantiate the selection?

PS I would need somehow to first make the selection based on the parameter and retrieve something from the factory and then that something to get its dependencies in order to create the final object.

One good way of doing this is to use a DI library and to then inject whatever container it provides into the factory; the factory is then only deciding based on the passed parameters what type it should return, and then delegating to the container to construct that object for return.

This has some benefits

  • It lets you separate the lifecycle of these dependent objects (and indeed, the constructed objects) from the factory
  • It decouples the factory from having to know how to construct all the possible object graphs it provides and lets it focus on making the decision on what to build, not how to build it

eg

public class SimpleFoo: Foo
{
    public  SimpleFoo(IServiceA a){...}
}

public class ComplexFoo: Foo
{
    public  ComplexFoo(IServiceA a, IServiceB b){...}
}

public class DegenerateFoo: Foo
{
    public DegenerateFoo(){..does nothing...}
}

public class FooFactory
{    
    readonly IContainer _container;
    public void FooFactory(IContainer container){_container=container;}

    public Foo GetAFoo(int type)
    {
       switch (type)
       {
            case 0:
                return _container.Get<SimpleFoo>();
            case 1:
                return _container.Get<ComplexFoo>();
            default:
                //unknown case, return some kind of Foo that does nothing
                return _container.get<DegenerateFoo>();
       }
    }
}

Your container, meanwhile, would have been separately configured somewhere else in the application's "Composition Root" to know how to resolve the object graphs (the following is pseudocode only)

container.RegisterTransient<IServiceA, ServiceAImplementation>();
container.RegisterSingleton<IServiceB, ServiceBImplementation>();

In this case we're configuring that any IServiceA injection is a new object instance each time it is requested; whereas IServiceB injections will be a single shared instance that the container takes care of creating once and doling out on request. Of course this is just an example of how you might configure these, ultimately you know best how you need to configure the lifetimes of these dependencies.

Hope you get the idea.

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