Repository Pattern یا ریپازیتوری پترن یک مرز بین منطق دامنه و جزئیات دسترسی به داده ایجاد می‌کند. سرویس ثبت سفارش به قراردادی مانند OrderRepository وابسته می‌شود، نه لزوماً به مدل ORM یا کوئری SQL. این الگو برای همه پروژه‌های CRUD الزامی نیست.

PHP: قرارداد و پیاده‌سازی با Eloquent

interface OrderRepository {
    public function find(int $id): ?Order;
}
class EloquentOrderRepository implements OrderRepository {
    public function find(int $id): ?Order {
        return Order::find($id);
    }
}
class OrderService {
    public function __construct(private OrderRepository $orders) {}
    public function get(int $id): ?Order { return $this->orders->find($id); }
}
// In AppServiceProvider::register()
$this->app->bind(OrderRepository::class, EloquentOrderRepository::class);

Python: پروتکل و پیاده‌سازی

from typing import Protocol
class OrderRepository(Protocol):
    def find(self, order_id: int): ...

class SqlOrderRepository:
    def __init__(self, connection): self.connection = connection
    def find(self, order_id):
        return self.connection.execute(
            'SELECT id, total FROM orders WHERE id = ?', (order_id,)
        ).fetchone()

C# با Entity Framework Core

public interface IOrderRepository { Task<Order?> FindAsync(int id); }
public sealed class EfOrderRepository(AppDbContext db) : IOrderRepository {
    public Task<Order?> FindAsync(int id) => db.Orders.FindAsync(id).AsTask();
}
// Program.cs
builder.Services.AddScoped<IOrderRepository, EfOrderRepository>();

مزیت و هزینه

مزیتهزینه
جدا کردن وابستگی سرویس از دیتابیسکلاس و Interface بیشتر
امکان جایگزینی پیاده‌سازی در تستاحتمال ساخت abstraction تکراری بر ORM
کنترل کوئری‌های تخصصی در یک مرزامکان پنهان شدن قابلیت‌های کاربردی ORM

نکته فنی

اگر فقط تمام متدهای ORM را یک‌به‌یک در ریپازیتوری کپی می‌کنید، ممکن است لایه تازه ارزشی اضافه نکند. ابتدا مرز دامنه و سناریوهای تغییر واقعی را مشخص کنید.

اصطلاحات مرتبط: اینترفیس، سرویس کانتینر، سرویس کانتینر، تزریق وابستگی، معماری تمیز، واحد کار، الوکوئنت.