Lab 12: Design Patterns
Objective
Time
Prerequisites
Tools
Lab Instructions
Step 1: Creational Patterns — Singleton & Factory
docker run --rm zchencow/innozverse-python:latest python3 -c "
from __future__ import annotations
from typing import ClassVar
import threading
# --- Singleton (thread-safe) ---
class Config:
_instance: ClassVar[Config | None] = None
_lock: ClassVar[threading.Lock] = threading.Lock()
def __new__(cls) -> Config:
if cls._instance is None:
with cls._lock:
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._instance._settings = {
'db_url': 'sqlite:///store.db',
'api_key': 'secret',
'debug': False,
}
return cls._instance
def get(self, key: str, default=None):
return self._settings.get(key, default)
def set(self, key: str, value) -> None:
self._settings[key] = value
c1, c2 = Config(), Config()
c1.set('debug', True)
print('Same instance:', c1 is c2)
print('c2.debug:', c2.get('debug')) # True — same object
# --- Factory Method ---
from abc import ABC, abstractmethod
from dataclasses import dataclass
class Exporter(ABC):
@abstractmethod
def export(self, data: list[dict]) -> str: ...
class JsonExporter(Exporter):
def export(self, data):
import json
return json.dumps(data, indent=2)
class CsvExporter(Exporter):
def export(self, data):
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 TsvExporter(Exporter):
def export(self, data):
if not data: return ''
return '\n'.join('\t'.join(str(v) for v in row.values()) for row in data)
def exporter_factory(fmt: str) -> Exporter:
exporters = {'json': JsonExporter, 'csv': CsvExporter, 'tsv': TsvExporter}
cls = exporters.get(fmt)
if cls is None:
raise ValueError(f'Unknown format: {fmt!r}. Choose from {list(exporters)}')
return cls()
products = [
{'id': 1, 'name': 'Surface Pro', 'price': 864.0},
{'id': 2, 'name': 'Surface Pen', 'price': 49.99},
]
for fmt in ['json', 'csv', 'tsv']:
exp = exporter_factory(fmt)
result = exp.export(products)
print(f'--- {fmt.upper()} ---')
print(result[:80])
"Step 2: Behavioral Patterns — Observer & Strategy
Steps 3–8: Command, Builder, Composite, Adapter, Template Method, Capstone
Summary
Pattern
Category
Python idiom
Further Reading
Last updated
