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("שגיאה קריטית")