Wat zijn enkele voorbeelden van eenvoudige ontwerppatronen die in verschillende projecten kunnen worden gebruikt?
Oké, laten we enkele eenvoudige ontwerppatronen verkennen die nuttig kunnen zijn bij verschillende projecten. Deze patronen zijn relatief eenvoudig te begrijpen en te implementeren, en ze kunnen de codekwaliteit, onderhoudbaarheid en herbruikbaarheid aanzienlijk verbeteren.
1. Singleton
* Doel: Zorgt ervoor dat er slechts één exemplaar van een klasse wordt gemaakt en biedt een globaal toegangspunt tot dat exemplaar.
* Wanneer gebruiken: Wanneer u één enkele, gedeelde bron nodig heeft (bijvoorbeeld configuratiemanager, databaseverbindingspool, logger).
print(instance1 is instance2) # Uitvoer:True (ze zijn hetzelfde object)
```
* Opmerkingen: Wees voorzichtig met Singletons in omgevingen met veel multithreading. Mogelijk moet u vergrendelingsmechanismen toevoegen om de veiligheid van threads te garanderen tijdens het maken van exemplaren. Overmatig gebruik van Singletons kan leiden tot een nauwe koppeling en het testen bemoeilijken.
2. Fabrieksmethode
* Doel: Definieert een interface voor het maken van een object, maar laat subklassen beslissen welke klasse moet worden geïnstantieerd. Het ontkoppelt de clientcode van de specifieke klasse die wordt gemaakt.
* Wanneer gebruiken: Wanneer u objecten van verschillende typen moet maken op basis van een bepaalde voorwaarde of configuratie, en u wilt voorkomen dat de logica voor het maken van objecten rechtstreeks in de clientcode wordt vastgelegd.
* Opmerkingen: Met de Factory-methode kunt u nieuwe knoptypen toevoegen zonder de klasse `ButtonFactory` rechtstreeks te wijzigen (open/gesloten principe).
3. Strategie
* Doel: Definieert een familie van algoritmen, kapselt ze allemaal in en maakt ze uitwisselbaar. Strategie zorgt ervoor dat het algoritme onafhankelijk kan variëren van de klanten die het gebruiken.
* Wanneer gebruiken: Wanneer u meerdere manieren heeft om een specifieke taak uit te voeren en u tijdens runtime gemakkelijk hiertussen wilt kunnen schakelen.
cart1.checkout() # Uitvoer:$ 150 betalen met creditcard:1234-5678-9012-3456
winkelwagen2 =Winkelwagen(paypal)
winkelwagen2.add_item(200)
cart2.checkout() # Uitvoer:$ 200 betalen met PayPal:[email protected]
```
* Opmerkingen: De `Winkelwagen` hoeft de specifieke betaalmethode niet te kennen. Het gebruikt eenvoudigweg de geïnjecteerde 'PaymentStrategy' om de betaling uit te voeren. Dit maakt het gemakkelijk om nieuwe betaalmethoden toe te voegen zonder de klasse `ShoppingCart` te wijzigen.
4. Waarnemer
* Doel: Definieert een één-op-veel-afhankelijkheid tussen objecten, zodat wanneer een object van status verandert, alle afhankelijke objecten automatisch op de hoogte worden gesteld en worden bijgewerkt.
* Wanneer gebruiken: Wanneer een verandering in één object het veranderen van andere objecten vereist, en u niet wilt dat de objecten nauw met elkaar verbonden zijn. Voorbeelden:gebeurtenisafhandeling, UI-updates, model-view-controller (MVC)-architectuur.
* Eenvoudig voorbeeld (Python):
```python
klasse Onderwerp:
def __init__(zelf):
zelf._observers =[]
def hechten(zelf, waarnemer):
self._observers.append(waarnemer)
def losmaken(zelf, waarnemer):
self._observers.remove(waarnemer)
def melden (zelf, bericht):
voor waarnemer in zichzelf._waarnemers:
waarnemer.update(bericht)
klasse Waarnemer:
def update(zelf, bericht):
verhogen NotImplementedError()
klasse ConcreteObserverA(Observer):
def update(zelf, bericht):
print(f"Waarnemer A ontvangen:{bericht}")
klasse ConcreteObserverB(Observer):
def update(zelf, bericht):
print(f"Waarnemer B ontvangen:{message.upper()}")
# Gebruik
onderwerp =Onderwerp()
waarnemer_a =ConcreteObserverA()
waarnemer_b =BetonObserverB()
onderwerp.attach(waarnemer_a)
onderwerp.attach(waarnemer_b)
subject.notify("Hallo wereld!") # Uitvoer:Waarnemer A ontvangen:Hallo wereld!
# Waarnemer B ontving:HALLO, WERELD!
onderwerp.detach(waarnemer_a)
subject.notify("Tot ziens!") # Uitvoer:Waarnemer B ontvangen:TOT DAUW!
```
* Opmerkingen: Het 'Onderwerp' houdt een lijst bij van 'Waarnemers'. Wanneer de status van het 'Subject' verandert (in dit geval wanneer 'notify' wordt aangeroepen), doorloopt het de lijst en roept de 'update'-methode op elke 'Observer' aan.
5. Sjabloonmethode
* Doel: Definieert het skelet van een algoritme in een basisklasse, maar laat subklassen specifieke stappen van het algoritme overschrijven zonder de structuur ervan te veranderen.
* Wanneer gebruiken: Wanneer u een reeks stappen heeft die in een specifieke volgorde moeten worden uitgevoerd, maar sommige van deze stappen kunnen variëren, afhankelijk van de specifieke implementatie.
* Eenvoudig voorbeeld (Python):
```python
klasse Gegevensprocessor:
def procesgegevens(zelf):
self.read_data()
self.validate_data()
self.transform_data()
self.save_data()
print("Gegevensverwerking voltooid.")
def read_data(zelf):
verhogen NotImplementedError()
def validate_data(zelf):
print("Standaardvalidatie:controleren op nulwaarden.")
def transform_data(zelf):
verhogen NotImplementedError()
def save_data(zelf):
verhogen NotImplementedError()
klasse CSVDataProcessor(GegevensProcessor):
def read_data(zelf):
print("Gegevens uit CSV-bestand lezen.")
def transform_data(zelf):
print("CSV-gegevens transformeren.")
def save_data(zelf):
print("Gegevens opslaan in database.")
klasse JSONDataProcessor(GegevensProcessor):
def read_data(zelf):
print("Gegevens uit JSON-bestand lezen.")
def validate_data(zelf):
print("Aangepaste validatie voor JSON-gegevens:schema controleren.")
def transform_data(zelf):
print("JSON-gegevens transformeren.")
def save_data(zelf):
print("Gegevens opslaan in JSON-bestand.")
# Gebruik
csv_processor =CSVDataProcessor()
csv_processor.process_data()
# Uitvoer:
# Gegevens uit CSV-bestand lezen.
# Standaardvalidatie:controleren op nulwaarden.
# CSV-gegevens transformeren.
# Gegevens opslaan in database.
# Gegevensverwerking voltooid.
json_processor =JSONDataProcessor()
json_processor.process_data()
# Uitgang:
# Gegevens uit JSON-bestand lezen.
# Aangepaste validatie voor JSON-gegevens:schema controleren.
# JSON-gegevens transformeren.
# Gegevens opslaan in JSON-bestand.
# Gegevensverwerking voltooid.
```
* Opmerkingen: De 'DataProcessor' definieert de algemene structuur van het gegevensverwerkingsalgoritme. Subklassen zoals `CSVDataProcessor` en `JSONDataProcessor` bieden specifieke implementaties voor de stappen `read_data`, `transform_data` en `save_data`. De stap `validate_data` kan worden overschreven of de standaardimplementatie worden gebruikt.
6. Decorateur
* Doel: Voegt dynamisch verantwoordelijkheden toe aan een object zonder de klasse ervan te wijzigen. Decorateurs bieden een flexibel alternatief voor subklassen om de functionaliteit uit te breiden.
* Wanneer gebruiken: Wanneer u tijdens runtime functionaliteit aan een object wilt toevoegen, zonder andere objecten van dezelfde klasse te beïnvloeden. Handig voor het toevoegen van logboekregistratie, caching of autorisatie.
* Opmerkingen: De `CoffeeDecorator` biedt een basisklasse voor decorateurs. Elke decorateur (bijvoorbeeld `MilkDecorator`, `SugarDecorator`) omhult het originele `Koffie`-object en voegt zijn eigen functionaliteit toe (in dit geval voegt hij kosten en beschrijving toe).
Belangrijke overwegingen bij het kiezen van een patroon:
* Begrijp het probleem: Definieer duidelijk het probleem dat u probeert op te lossen voordat u naar een patroon zoekt. Pas niet blindelings patronen toe; gebruik ze als hulpmiddelen om uw code te verbeteren.
* Eenvoud: Begin met de eenvoudigste oplossing die aan uw behoeften voldoet. Over-engineer de dingen niet voortijdig.
* Context: Het beste patroon hangt af van de specifieke context van uw project, de taal die u gebruikt en de bestaande codebase.
* Testen: Ontwerppatronen moeten uw code beter testbaar maken, niet minder. Zorg ervoor dat u eenvoudig unit-tests kunt schrijven voor de componenten die u gebruikt.
Dit zijn slechts enkele voorbeelden van eenvoudige ontwerppatronen. Naarmate u meer ervaring opdoet, leert u situaties herkennen waarin deze en andere patronen kunnen worden toegepast om robuustere, onderhoudbare en herbruikbare code te creëren. Succes!