Predvoditelev.RU
Заметки

Именование классов и интерфейсов для получения экземпляра объекта по имени

Интерфейс для получения экземпляра объекта по названию его класса или идентификатору может быть назван по разному, в зависимости от того, какая логика подразумевается (но не обязательно будет) в реализации.

Я пришёл к таким названиям:

Container — будет возвращаться всегда один и тот же объект;

Factory — каждый раз будет возвращаться новый объект;

Resolver — не важно, какая будет реализация.

При этом в случае конкретного класса имеет смысл называть его по логике, которую он реализует. Например, для интерфейса MyClassResolver может быть как реализация MyClassContainer, так и MyClassFactory.

Container

Классический пример  — интерфейс контейнера PSR-11.

interface ContainerInterface
{
    public function get(string $id);
    public function has(string $id): bool;
}

В документации сказано:

Two successive calls to get with the same identifier SHOULD return the same value. 

То есть, при вызов метода get() с одним и тем же идентификатором рекомендуется (но не обязательно) возвращать одно и тоже значение.

Большинство реализаций PSR-11 контейнера создают объект один раз и при последующих запросах возвращают его же (например, Yii Dependency Injection и PHP-DI). Некоторые реализации позволяют настроить, в каких случаях объект создавать заново, а в каких нет (например, контейнер в Laravel).

Factory

Хороший пример фабричных интерфейсов есть в стандарте PSR-17.

Интерфейс фабрики для создания объекта клиентского запроса:

interface RequestFactoryInterface
{
    public function createRequest(string $method, $uri): RequestInterface;
}

Интерфейс фабрики для создания объекта ответа сервера:

interface ServerRequestFactoryInterface { 
    public function createServerRequest(
        string $method,
        $uri,
        array $serverParams = []
    ): ServerRequestInterface;
}

Resolver

Это название используется валидаторе Yii3 для интерфейса объекта, возвращающего обработчик правила валидации по имени правила:

interface RuleHandlerResolverInterface
{
    public function resolve(string $className): RuleHandlerInterface;
}
@sergei_predvoditelev — Авторский канал в Telegram: заметки о веб-разработке, PHP, открытом ПО, развитии и немного о жизни.