For example, my DependentClass depends on some AbstractCsv class. Here is the declaration of AbstractCsv's factory (http://ift.tt/1FxCeSm):
public static AbstractCsv::createFromFileObject(SplFileObject $obj): AbstractCsv
And here is the declaration of DependentClass's constructor:
class DependentClass {
public function __construct(AbstractCsv $csv) { /* implementation... */ }
// implementation...
}
As you can see, to instantiate AbstractCsv, I need to pass in an instance of SplFileObject to dependency's factory function AbstractCsv::createFromFileObject. To create an SplFileObject, I need a filename. DependentClass stores the filename needed (or, for example, the filename is calculated dynamically within DependentClass at runtime).
How can I pass an instance of AbstractCsv into the DependentClass's constructor, if:
- the filename is defined inside the
DependentClassitself, - and also to create an instance of
AbstractCsv, I first have to create anSplFileObjectand then anAbstactCsv? It is a vicious circle!
I currently see the only solution to break this circle: DependentClass should not depend on AbstractCsv, but on its factory which will provide an instance of AbstractCsv to DependentClass on-demand. This also will eliminate the need to create SplFileObject within the DependentClass:
class DependentClass {
public function __construct(CsvProvider $csvProvider) { /* implementation... */ }
// implementation...
public function someMethod($value) {
$filename = rand($value); // somehow calculate $filename
$csvFile = $this->csvProvider($filename);
$csvFile->fwrite($someData);
}
}
class CsvProvider {
public function get(string $filename) : AbstractCsv {
return AbstractCsv::createFromFileObject(new SplFileObject($filename));
}
}
I think, this problem is common and occurs very often, right? I'm currently new to DI, so I wonder: is this solution really the right way to solve this problem? And what's the name of such factories? I called it provider. Is it a correct term for this?
Aucun commentaire:
Enregistrer un commentaire