> For the complete documentation index, see [llms.txt](https://myroslavs-organization.gitbook.io/orm/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://myroslavs-organization.gitbook.io/orm/system-architecture-and-implementation/support-of-various-databases/implementation-using-a-pattern-strategy.md).

# Implementation using a pattern strategy

**Strategy Pattern** is a behavioral design pattern that allows choosing the behavior of an algorithm at runtime. In the context of an ORM (Object-Relational Mapping) system, this pattern is particularly useful for supporting multiple database systems, such as PostgreSQL and MySQL, without binding the `DatabaseManager` class to a specific database implementation.

**Concept Overview**

In my ORM system, the Strategy pattern is implemented using classes that encapsulate logic specific to each database. The `DatabaseManager` class acts as the context and dynamically selects the appropriate strategy depending on the database type. The strategy is a representation of various database operations adapted to a specific database (e.g., PostgreSQL or MySQL).

**Code Implementation**

Here’s how the Strategy pattern is applied in my system:

1. `DatabaseManager` Class: The context class that holds a reference to the strategy object.

```typescript
class DatabaseManager<DT extends DatabasesTypes> implements DatabaseManagerInterface<DT> {
    private _connectionData: ConnectionData;
    private _dataSource: DataSourceContextInterface<DT>;

    constructor(connectionData: ConnectionData, dataSource: DataSourceContextInterface<DT>) {
        this._dataSource = dataSource;
        this._dataSource.connectionData = this._connectionData;
        
        if (connectionData.type === DatabasesTypes.POSTGRES) {
            this._dataSource.database = new DataSourcePostgres() as unknown as DataSourceInterface<DT>;
        }

        if (this._connectionData.type === DatabasesTypes.MYSQL) {
            this._dataSource.database = new DataSourceMySql() as unknown as DataSourceInterface<DT>;
        }
    }
}
```

* The `DatabaseManager` class initializes the corresponding `DataSource` based on the `connectionData.type`.
* This class is the entry point that sets up the correct strategy.

2. `DataSourceContext` class: A context for storing the strategy.

```typescript
class DataSourceContext<DT extends DatabasesTypes> implements DataSourceContextInterface<DT> {
    set database(dataSource: DataSourceInterface<DT>) {
        this._dataSource = dataSource;
    }
}
```

* The `DataSourceContext` class allows you to dynamically set the strategy (database) using the `database` method.

3. **Specific Strategy (PostgreSQL)**: Implements operations specific to PostgreSQL.

```typescript
export class DataSourcePostgres extends BaseQueries implements DataSourceInterface<DatabasesTypes.POSTGRES> {
    client: PoolClient;
    private _tableBuilder: TableBuilderInterface;
    private _tableAlterer: TableAltererInterface;
    private _migrationService: MigrationServiceInterface;
    private _selectQueries: SelectQueriesInterface;
    private _insertQueries: InsertQueriesInterface;
    private _updateQueries: UpdateQueriesInterface;
    private _deleteQueries: DeleteQueriesInterface;
    private _aggregateQueries: AggregateQueriesInterface;
    private _structureQueries: StructureQueriesInterface;
    private _viewQueries: ViewQueriesInterface;
    private _triggerAlterer: TriggerAltererInterface;
    private _indexAlterer: IndexAltererInterface;
    private _transaction: TransactionInterface;
    private _monitoring: MonitoringInterface<DatabasesTypes.POSTGRES>;

    constructor() {
        super();
        this._migrationService = new MigrationService();
        this._tableBuilder = new TableBuilder();
        this._tableAlterer = new TableAlterer();
        this._selectQueries = new SelectQueries();
        this._insertQueries = new InsertQueries();
        this._updateQueries = new UpdateQueries();
        this._deleteQueries = new DeleteQueries();
        this._aggregateQueries = new AggregateQueries();
        this._structureQueries = new StructureQueries();
        this._viewQueries = new ViewQueries();
        this._triggerAlterer = new TriggerAlterer();
        this._indexAlterer = новий IndexAlterer();
        this._transaction = new Transaction();
        this._monitoring = new Monitoring();
    }

    async connect(dataToConnect: ConnectionData): Promise<void> {
        const pool = new Pool(dataToConnect);
        this.client = await pool.connect();
    }

    createTable(options: CreateTableOptionsInterface<DatabasesTypes.POSTGRES>): string {
        return this._tableBuilder.createTable(
            options?.table,
            options?.columns,
            options?.computedColumns,
            options?.foreignKeys,
            options?.primaryColumn,
            options?.oneToOne,
            options?.oneToMany
        );
    }
}
```

* `DataSourcePostgres` Class encapsulates all PostgreSQL-specific operations, such as table creation, migration management, and query handling.
* By adhering to the `DataSourceInterface`, it ensures seamless switching between different database strategies in `DatabaseManager`.

**Why the Strategy Pattern is Useful:**

1. **Flexibility**: The Strategy Pattern allows easy switching between different types of databases by simply selecting the appropriate strategy. This is particularly useful in systems that need to support multiple databases.
2. **Ease of Maintenance**: By encapsulating database-specific logic in separate classes, I can manage and update each strategy independently. If PostgreSQL changes its API, I only need to update the `DataSourcePostgres` class without affecting other parts of the system.
3. **Scalability**: As my ORM system grows and starts supporting more databases, I can add new strategies without needing to modify existing code. Simply implement a new `DataSource` class and connect it to `DatabaseManager`.

This approach provides adaptability to different database environments and ease of maintenance over time, making it a robust solution for handling complex database operations.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://myroslavs-organization.gitbook.io/orm/system-architecture-and-implementation/support-of-various-databases/implementation-using-a-pattern-strategy.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
