D
D
Daria Motorina2021-11-14 20:41:06
symfony
Daria Motorina, 2021-11-14 20:41:06

How to refactor classes with heterogeneous constructors?

The Symfony tag is listed as the question is about its Dependency Injection.

Project on Symfony 5.0.
How can you optimally refactor code that has several classes of the same child, but they have different constructors, while class creation is assigned to the factory?
I wanted to get away from disparate constructors, but this is only achieved by not injecting into constructors.

Conditional classes:

<?php

abstract class A {...}

class A1 extends A
{
    public function __construct($a, $b, $c) {/*...*/}
}

class A2 extends A
{
    public function __construct($a, $d, $e) {/*...*/}
}

class AN extends A
{
    public function __construct($a) {/*...*/}
}

class Factory
{
    public function create($type) {
        switch($type) {
            case 1:
                $object =  new A1($a, $b, $c);
            case 2:
                $object =  new A2($a, $d, $e);
            case N:
                $object =  new A1($a);
        }
    }
}


I have had several attempts to refactor this solution and all failed. All arguments $a, $b, $c, $d, $e are needed, they are integral attributes of the classes they are injected into.
Classes A1...AN differ by 20-30 percent and there is no point in deviating from the common denominator, except to put this logic into a trait, but this will not solve anything.
I can't use Setter Injection to take out the parameters $b,$c and $d, $e, because that does nothing, the class is created inside the factory.
If the factory is abandoned, then the same $a ... $e parameters will have to be forwarded to the service, where all A1 ... ANs are created and used.
Now I have a crutch in the form that all $a...$e parameters are passed to the factory constructor, but this is illogical and will inflate its constructor even more in the future.

Is there some simpler solution that I'm missing? I will be glad to ideas and links to sources of similar solutions

Answer the question

In order to leave comments, you need to log in

2 answer(s)
F
Flying, 2021-11-14
@glaphire

I would use a service locator to generate a list of services and pass it to the factory constructor.
Alternatively, you could define the factory as a service subscriber , in which case building the service locator would probably be even easier.
If in some way (for example, through a common interface or a static method of a factory class), you define a list of services that a factory can create, then you can create a compiler pass that will form a service locator at the container compilation stage by analyzing their dependencies. This is a little more complicated, but it won't require you to edit the code when expanding the list of classes generated by the factory.

M
Maxim Fedorov, 2021-11-14
@Maksclub

Usually, REgistry
FooInterface
Service1Foo
Service2Foo
Service3Foo FooRegistry is
done through tags or through call, specific services are registered, in the factory we get through type (if through call regalia with the right key) or in a cycle, banishing each dependency and calling supports($type) for each of the services

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question