Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

If several Laravel classes construct the same implementation with new, changing that implementation means changing each caller. You can reduce that coupling by depending on an interface and letting Laravel’s service container resolve its bound implementation. That approach addresses a related object-creation problem, but it is not automatically the classic Factory Method design pattern—and new is not inherently bad.

What Factory Method means—and what it does not

In the classic Factory Method pattern, a creator delegates product creation to a method whose implementation can vary, traditionally through creator subclasses. The caller works with a product abstraction instead of choosing and constructing a concrete product itself.

Laravel’s service container can solve a similar coupling concern by resolving dependencies and mapping interfaces to implementations. It is a framework-managed dependency-resolution mechanism, however, not necessarily a literal GoF Factory Method. The distinction matters: use the name of the mechanism you actually have, rather than calling every object-returning method or container binding a factory method.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How to avoid scattered construction in Laravel

Suppose several consumers instantiate new SmtpNotifier() directly. If you later want a different notifier, those callers know too much about the concrete class. When there is a genuine implementation choice, define an interface, bind it to the chosen implementation, and type-hint the interface in consumers Laravel resolves.

1. Define the contract and implementation

<?php

namespace AppContracts;

interface Notifier
{
    public function send(string $message): void;
}
<?php

namespace AppServices;

use AppContractsNotifier;

class SmtpNotifier implements Notifier
{
    public function send(string $message): void
    {
        // Send the message using SMTP.
    }
}

2. Register the interface binding

Laravel’s service-provider documentation places service bindings in a provider’s register method. For example, in an application service provider:

<?php

namespace AppProviders;

use AppContractsNotifier;
use AppServicesSmtpNotifier;
use IlluminateSupportServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        $this->app->bind(Notifier::class, SmtpNotifier::class);
    }
}

With this binding, a request for Notifier can be fulfilled with SmtpNotifier. The binding removes the need for each consumer to name that implementation.

3. Type-hint the contract in a consumer

<?php

namespace AppServices;

use AppContractsNotifier;

class WelcomeMessage
{
    public function __construct(private Notifier $notifier)
    {
    }

    public function send(): void
    {
        $this->notifier->send('Welcome');
    }
}

When Laravel constructs a framework-managed class such as a controller, it can resolve type-hinted dependencies through the container. You generally do not need to call the container manually for ordinary constructor injection in framework-managed entry points.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choose the simplest creation mechanism that fits

Avoiding new is not an objective by itself. If a class always needs one straightforward concrete dependency and there is no meaningful variation, direct construction or ordinary constructor injection may be clearer than adding an interface, binding, and factory class. Laravel does not require an abstraction for every class.

When there is a real choice, compare who should make it and how often that choice can change:

Mechanism Who chooses the implementation? When it fits Trade-off
Direct construction with new The caller A simple, stable dependency with no meaningful implementation choice Callers are coupled to the concrete class they construct.
Explicit factory The factory, based on its creation rule or input Creation logic or runtime selection is substantial enough to deserve a dedicated place Adds a class and indirection; useful when it clarifies a changing creation rule, not merely to hide one constructor call.
Container binding and constructor injection The container uses the registered mapping A consumer should depend on a contract and Laravel can resolve it at a framework-managed entry point Requires a binding for an interface and can make resolution less explicit if callers reach into the container dynamically.

Constructor injection also gives tests a seam: a consumer typed to an interface can receive a substitute implementation without changing its own code. Prefer passing dependencies in through the constructor over resolving them dynamically inside the consumer when ordinary injection works.

Do not confuse service resolution with Eloquent model factories

Laravel Eloquent factories serve a different purpose: they define model attributes for database seeding and tests. The framework documents generating one with php artisan make:factory; factories are conventionally discovered, and models can access them through the HasFactory trait. They are useful for producing model data, not a synonym for a runtime Factory Method that selects service implementations.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Laravel documentation

These links describe Laravel 13.x. Check the documentation for your application’s Laravel version if its provider setup or conventions differ.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.