לדלג לתוכן

2.1 תבניות יצירה פתרון

תרגיל 1 - Factory - פתרון

import json
from abc import ABC, abstractmethod


class ReportExporter(ABC):
    @abstractmethod
    def export(self, data: list) -> str:
        pass


class JsonExporter(ReportExporter):
    def export(self, data: list) -> str:
        return json.dumps(data, ensure_ascii=False, indent=2)


class CsvExporter(ReportExporter):
    def export(self, data: list) -> str:
        if not data:
            return ""
        headers = ",".join(data[0].keys())
        rows = [",".join(str(v) for v in row.values()) for row in data]
        return "\n".join([headers] + rows)


class TxtExporter(ReportExporter):
    def export(self, data: list) -> str:
        lines = []
        for i, item in enumerate(data, 1):
            lines.append(f"{i}. {item.get('title', item)}")
            for key, value in item.items():
                if key != "title":
                    lines.append(f"   {key}: {value}")
        return "\n".join(lines)


def create_exporter(format: str) -> ReportExporter:
    exporters = {
        "json": JsonExporter,
        "csv": CsvExporter,
        "txt": TxtExporter
    }
    exporter_class = exporters.get(format.lower())
    if exporter_class is None:
        raise ValueError(f"פורמט לא נתמך: {format}. פורמטים זמינים: {list(exporters.keys())}")
    return exporter_class()


# בדיקה
tasks = [
    {"title": "תקן באג", "status": "in_progress", "priority": "high"},
    {"title": "כתוב בדיקות", "status": "todo", "priority": "normal"}
]

print(create_exporter("json").export(tasks))
print(create_exporter("csv").export(tasks))
print(create_exporter("txt").export(tasks))

תרגיל 2 - Builder - פתרון

class QueryBuilder:
    def __init__(self, table: str):
        self._table = table
        self._columns = ["*"]
        self._conditions = []
        self._params = []
        self._order_by = None
        self._descending = False
        self._limit = None

    def select(self, *columns: str) -> "QueryBuilder":
        self._columns = list(columns)
        return self

    def where(self, column: str, value) -> "QueryBuilder":
        self._conditions.append(f"{column}=?")
        self._params.append(value)
        return self

    def order_by(self, column: str, descending: bool = False) -> "QueryBuilder":
        self._order_by = column
        self._descending = descending
        return self

    def limit(self, count: int) -> "QueryBuilder":
        self._limit = count
        return self

    def build(self) -> tuple[str, tuple]:
        query = f"SELECT {', '.join(self._columns)} FROM {self._table}"
        if self._conditions:
            query += " WHERE " + " AND ".join(self._conditions)
        if self._order_by:
            direction = "DESC" if self._descending else "ASC"
            query += f" ORDER BY {self._order_by} {direction}"
        if self._limit is not None:
            query += f" LIMIT {self._limit}"
        return query, tuple(self._params)


# בדיקה
query, params = (
    QueryBuilder("tasks")
    .select("id", "title", "status")
    .where("owner_id", 5)
    .where("status", "in_progress")
    .order_by("created_at", descending=True)
    .limit(10)
    .build()
)
print(query)
print(params)

תרגיל 3 - Singleton - פתרון

from datetime import datetime


class AppLogger:
    _instance = None

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

    def _log(self, level: str, message: str):
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        print(f"[{timestamp}] {level}: {message}")

    def info(self, message: str):
        self._log("INFO", message)

    def warning(self, message: str):
        self._log("WARNING", message)

    def error(self, message: str):
        self._log("ERROR", message)


# בדיקה
logger1 = AppLogger()
logger2 = AppLogger()

print(logger1 is logger2)  # True

logger1.info("משתמש התחבר")
logger2.warning("ניסיון כושל")
logger1.error("שגיאה קריטית")