# 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.

```php
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.

```php
$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.

```php
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.

```php
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.

```php
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;
    }
}
```
