Menu
Coddy logo textTech

Wzorzec Strategy

Część sekcji Programowanie obiektowe ścieżki Python w Coddy. Lekcja 48 z 64.

Wzorzec Strategia definiuje rodzinę algorytmów, hermetyzuje każdy z nich i umożliwia ich wzajemną wymianę. Możesz przełączać algorytmy w czasie działania programu bez zmieniania kodu klienta.

Oto proste klasy strategii dla różnych metod płatności:

class CreditCard:
    def pay(self, amount):
        return f"Paid ${amount} with Credit Card"

class PayPal:
    def pay(self, amount):
        return f"Paid ${amount} with PayPal"

class Bitcoin:
    def pay(self, amount):
        return f"Paid ${amount} with Bitcoin"

Każda strategia implementuje tę samą metodę (pay), ale zachowuje się inaczej.

Utwórz klasę kontekstu, która używa strategii:

class ShoppingCart:
    def __init__(self):
        self.total = 0
        self.payment_strategy = None
    
    def add_item(self, price):
        self.total += price
    
    def set_payment_strategy(self, strategy):
        self.payment_strategy = strategy
    
    def checkout(self):
        return self.payment_strategy.pay(self.total)

Klasa kontekstu może przełączać się między różnymi strategiami płatności.

Użyj wzorca strategii:

cart = ShoppingCart()
cart.add_item(50)
cart.add_item(30)

# Użyj strategii płatności kartą kredytową
cart.set_payment_strategy(CreditCard())
print(cart.checkout())

# Przełącz na strategię płatności PayPal
cart.set_payment_strategy(PayPal())
print(cart.checkout())

Utwórz kolejny przykład ze strategiami sortowania:

class BubbleSort:
    def sort(self, data):
        return f"Bubble sorted: {sorted(data)}"

class QuickSort:
    def sort(self, data):
        return f"Quick sorted: {sorted(data)}"

class Sorter:
    def __init__(self, strategy):
        self.strategy = strategy
    
    def set_strategy(self, strategy):
        self.strategy = strategy
    
    def sort_data(self, data):
        return self.strategy.sort(data)

# Użyj różnych strategii sortowania
numbers = [3, 1, 4, 1, 5]

sorter = Sorter(BubbleSort())
print(sorter.sort_data(numbers))

sorter.set_strategy(QuickSort())
print(sorter.sort_data(numbers))

Wynik:

Paid $80 with Credit Card
Paid $80 with PayPal
Bubble sorted: [1, 1, 3, 4, 5]
Quick sorted: [1, 1, 3, 4, 5]

Kluczowa kwestia: Wzorzec Strategia pozwala zmieniać algorytmy w czasie działania programu. Zdefiniuj różne strategie z tym samym interfejsem, a następnie pozwól klasie kontekstu wybrać, której użyć. Dzięki temu Twój kod jest elastyczny i łatwy do rozszerzania o nowe algorytmy bez zmieniania istniejącego kodu.

challenge icon

Wyzwanie

Średni

Zaimplementuj nową strategię BitcoinPayment dla naszego systemu zakupów.

Twoje zadanie:

  1. Utwórz klasę BitcoinPayment implementującą PaymentStrategy
    • Powinna przyjmować wallet_address w konstruktorze
    • Metoda pay powinna wypisać dokładnie: Paying $X using Bitcoin wallet: Y, gdzie X to kwota, a Y to adres portfela
    • Po wypisaniu metoda pay powinna zwrócić True
  2. Napisz funkcję main, która:
    • Tworzy koszyk zakupowy
    • Dodaje do koszyka laptopa kosztującego $1200 i słuchawki kosztujące $100
    • Tworzy BitcoinPayment z adresem portfela "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"
    • Ustawia tę strategię płatności w koszyku
    • Wywołuje metodę checkout

Kod początkowy zawiera już na dole if __name__ == "__main__":. Nie musisz dodawać tego samodzielnie. To konwencja Pythona, która gwarantuje, że funkcja main() uruchomi się tylko wtedy, gdy plik zostanie wykonany bezpośrednio (a nie zaimportowany przez inny moduł). Wystarczy zdefiniować funkcję main(), a podany blok wywoła ją automatycznie.

Postępuj zgodnie z tą samą strukturą, co w przykładach z lekcji.

Spróbuj swoich sił

from abc import ABC, abstractmethod

class PaymentStrategy(ABC):
    @abstractmethod
    def pay(self, amount):
        pass

class CreditCardPayment(PaymentStrategy):
    def __init__(self, card_number, expiry_date, cvv):
        self.card_number = card_number
        self.expiry_date = expiry_date
        self.cvv = cvv
        
    def pay(self, amount):
        print(f"Paying ${amount} using Credit Card: {self.card_number}")
        return True

class PayPalPayment(PaymentStrategy):
    def __init__(self, email, password):
        self.email = email
        self.password = password
        
    def pay(self, amount):
        print(f"Paying ${amount} using PayPal account: {self.email}")
        return True

class ShoppingCart:
    def __init__(self):
        self.items = []
        self.payment_strategy = None
    
    def add_item(self, item, price):
        self.items.append({"item": item, "price": price})
    
    def set_payment_strategy(self, payment_strategy):
        self.payment_strategy = payment_strategy
    
    def checkout(self):
        total = sum(item["price"] for item in self.items)
        if self.payment_strategy:
            return self.payment_strategy.pay(total)
        else:
            raise ValueError("No payment strategy set")

# Utwórz tutaj klasę strategii BitcoinPayment


if __name__ == "__main__":
    main()
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator Python online