๐ŸญFactory Design Pattern

The Core Foundation package simplifies the implementation of the factory design pattern, enabling you to create flexible, maintainable, and scalable service classes effortlessly. Here's how you can leverage this feature to enhance your application's architecture.

Native Factory Design Pattern Support

The package provides native support for the factory design pattern. To use it, extend the CoreFoundation\Services\BaseService class in your service class.

class UserService extends BaseService
{
    public function __construct(
        protected UserRepositoryInterface $userRepository,
        protected ObjectMutable $objectMutable
    ) {
    }

    public function index(array $filterable = [], array $relationship = []): Collection|Paginator
    {
        $mutableBeforeData = $this->objectMutable->create([
            "filterable" => $filterable,
            "relationship" => $relationship
        ]);

        $this->interceptorEventDispatch(
            eventKey: "index.before",
            data: $mutableBeforeData
        );

        $filterable = $mutableBeforeData->get("filterable");
        $relationship = $mutableBeforeData->get("relationship");

        $users = $this->userRepository->fetchAll($filterable, $relationship);

        $this->objectMutable->create([
            "users" => $users,
        ]);

        $this->interceptorEventDispatch(
            eventKey: "index.after",
            data: $mutableAfterData
        );

        return $mutableAfterData->get("users");
    }
}

How to Use the Factory Pattern

To utilize the factory pattern in your services, you can simply call the factory method on your service instance.

$users = $this->userService->factory()->index($filterable);

Defining Factories in the Service Provider

To define a factory, set it in your service provider. This allows you to specify which class should be used as the factory.

UserService::setFactory(CustomUserService::class);

Factory Conditions

You can define conditions for selecting the appropriate factory class using either a closure method or a custom method.

Closure method

This method sets a global condition for choosing the factory class.

class AppServiceProvider extends ServiceProvider
{
    public function register()
    {
        UserService::setFactoryCondition(CustomUserService::class, function () {
            return app()->isProduction(); // return true/false
        });
    }
}

Custom method

This method allows you to add dynamic conditions based on your business logic.

class AppServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->singleton("custom.user.service", CustomUserConditionService::class); // binds "custom.user.service" key to service container.
        UserService::setFactoryCondition(CustomUserService::class, "custom.user.service");
    }
}

class CustomUserConditionService implements \CoreFoundation\Contracts\BaseFactoryConditionInterface
{
    public function __construct(
        //
    ) {
    }

    public function handle(): bool
    {
        // your custom logic

        return true;
    }
}

Last updated

Was this helpful?