[GO] Lernen Sie das Entwurfsmuster "Strategie" mit Python

Als Material zum Erlernen von GoF-Entwurfsmustern scheint das Buch "Einführung in Entwurfsmuster, die in der erweiterten und überarbeiteten Java-Sprache gelernt wurden" hilfreich zu sein. Da die aufgeführten Beispiele jedoch auf JAVA basieren, habe ich dieselbe Vorgehensweise mit Python versucht, um mein Verständnis zu vertiefen.

■ Strategiemuster (Strategiemuster)

Das Strategiemuster ist ein Entwurfsmuster, in dem zur Laufzeit Algorithmen im Bereich der Computerprogrammierung ausgewählt werden können. Das Strategiemuster enthält einen Verweis auf das Unterprogramm, das den Algorithmus innerhalb der Datenstruktur beschreibt. Zusätzlich zu Funktionszeigern, Funktionsobjekten und Delegaten werden Polymorphismus und Delegierung in orthodoxen objektorientierten Sprachen oder dynamische Ententypisierung durch Reflexion verwendet, um dieses Muster zu realisieren.

UML class and sequence diagram W3sDesign_Strategy_Design_Pattern_UML.jpg

UML class diagram strategy.png (Das Obige ist aus Wikipedia zitiert)

□ Memorandum

Das "Strategie" -Muster trennt absichtlich den Algorithmus-Teil von den anderen Teilen und gibt nur den Schnittstellenteil mit diesem Algorithmus an. Dann wird der Algorithmus durch Delegierung aus dem Programm verwendet. Wenn Sie beim Verbessern des Programms das Muster "Strategie" verwenden, müssen Sie nur die Rolle "ConcreteStrategy" ändern, wobei Sie darauf achten müssen, die Schnittstelle der Rolle "Strategie" nicht zu ändern, und die ** Delegierung erfolgt schrittweise. Da es Bindungen verwendet, ist es auch einfach, zwischen Algorithmen zu wechseln **.

■ Beispielprogramm "Strategie"

Eigentlich möchte ich versuchen, ein Beispielprogramm auszuführen, das das Strategiemuster verwendet, und das folgende Verhalten überprüfen. Hier kämpfen ** Taro ** und ** Hanako ** um den Sieg oder die Niederlage, indem sie Janken wiederholen.


Janken's Strategie

――Wenn Taro Janken schlägt, fordert er den nächsten Janken mit derselben Hand heraus.

$ python Main.py
Even...
Winner:[Hana: 1games,  0win,  0lose]
Winner:[Hana: 2games,  1win,  0lose]
Winner:[Hana: 3games,  2win,  0lose]
Even...
Winner:[Taro: 5games,  0win,  3lose]
Winner:[Hana: 6games,  3win,  1lose]
Winner:[Taro: 7games,  1win,  4lose]
Winner:[Hana: 8games,  4win,  2lose]
Even...

...(snip)

Winner:[Taro: 9976games,  2433win,  5070lose]
Winner:[Hana: 9977games,  5070win,  2434lose]
Winner:[Hana: 9978games,  5071win,  2434lose]
Winner:[Taro: 9979games,  2434win,  5072lose]
Winner:[Hana: 9980games,  5072win,  2435lose]
Even...
Winner:[Hana: 9982games,  5073win,  2435lose]
Even...
Even...
Winner:[Taro: 9985games,  2435win,  5074lose]
Winner:[Hana: 9986games,  5074win,  2436lose]
Winner:[Taro: 9987games,  2436win,  5075lose]
Winner:[Hana: 9988games,  5075win,  2437lose]
Winner:[Taro: 9989games,  2437win,  5076lose]
Winner:[Hana: 9990games,  5076win,  2438lose]
Winner:[Hana: 9991games,  5077win,  2438lose]
Winner:[Taro: 9992games,  2438win,  5078lose]
Winner:[Hana: 9993games,  5078win,  2439lose]
Winner:[Taro: 9994games,  2439win,  5079lose]
Winner:[Hana: 9995games,  5079win,  2440lose]
Winner:[Hana: 9996games,  5080win,  2440lose]
Winner:[Hana: 9997games,  5081win,  2440lose]
Winner:[Hana: 9998games,  5082win,  2440lose]
Even...
Total Result:
[Taro: 10000games,  2440win,  5083lose]
[Hana: 10000games,  5083win,  2440lose]

Das Ergebnis ist, dass die Janken-Strategie von ** hanako ** (Herausforderung Janken in der Reihenfolge "goo", "choki", "par") besser ist als die Janken-Strategie von ** Taro **. Ich tat. Dies liegt daran, dass die Janken-Strategie von ** Taro ** (wenn Sie die Janken gewinnen, fordern Sie die nächsten Janken mit derselben Hand heraus) niemals hintereinander gewinnt.

■ Details zum Beispielprogramm

Ähnlicher Code wurde in das Git-Repository hochgeladen. https://github.com/ttsubo/study_of_design_pattern/tree/master/Strategy

--Verzeichnisaufbau

.
├── Main.py
└── strategy
    ├── __init__.py
    ├── hand.py
    ├── player.py
    └── strategy.py

(1) Die Rolle der Strategie

Es ist die Rolle, die die Schnittstelle für die Verwendung der Strategie definiert. Im Beispielprogramm übernimmt die Klasse "Strategie" diese Rolle.

strategy/strategy.py


from abc import ABCMeta, abstractmethod

class Strategy(metaclass=ABCMeta):
    @abstractmethod
    def nextHand(self):
        pass

    @abstractmethod
    def study(self, win):
        pass

(2) Die Rolle von ConcreteStrategy

Es ist die Rolle, die tatsächlich die Schnittstelle der Rolle der "Strategie" implementiert. Hier programmieren Sie tatsächlich die spezifische Strategie (Arbeit, Richtlinie, Methode, Algorithmus). Im Beispielprogramm übernehmen die Klassen "WinningStrategy" und "CircularStrategy" diese Rolle.

strategy/strategy.py


import random
from strategy.hand import Hand

class WinningStrategy(Strategy):
    def __init__(self):
        self.__won = False
        self.__prevHand = None

    def nextHand(self):
        if not self.__won:
            self.__prevHand = Hand.getHand(random.randint(0, 2))
        return self.__prevHand

    def study(self, win):
        self.__won = win

class CircularStrategy(Strategy):
    def __init__(self):
        self.__Hand = 0

    def nextHand(self):
        return Hand.getHand(self.__Hand)

    def study(self, win):
        self.__Hand = (self.__Hand + 1) % 3

(3) Die Rolle des Kontexts

Es ist eine Rolle, die die Rolle "Strategie" verwendet. Ich habe eine Instanz der Rolle "ConcreteStrategy" und verwende sie nach Bedarf. Im Beispielprogramm übernimmt die Klasse "Player" diese Rolle.

strategy/player.py


class Player(object):
    def __init__(self, name, strategy):
        self.__name = name
        self.__strategy = strategy
        self.__wincount = 0
        self.__losecount = 0
        self.__gamecount = 0

    def nextHand(self):
        return self.__strategy.nextHand()

    def win(self):
        self.__strategy.study(True)
        self.__wincount += 1
        self.__gamecount += 1

    def lose(self):
        self.__strategy.study(False)
        self.__losecount += 1
        self.__gamecount += 1

    def even(self):
        self.__gamecount += 1

    def __str__(self):
        return "[{0}: {1}games,  {2}win,  {3}lose]".format(self.__name,
                                                           self.__gamecount,
                                                           self.__wincount,
                                                           self.__losecount)

(4) Die Rolle des Kunden

Im Beispielprogramm übernimmt die Methode "startMain" diese Rolle.

Main.py


import sys
import strategy.strategy
from strategy.strategy import WinningStrategy, CircularStrategy
from strategy.player import Player

def startMain():
    player1 = Player("Taro", WinningStrategy())
    player2 = Player("Hana", CircularStrategy())

    for _ in range(10000):
        nextHand1 = player1.nextHand()
        nextHand2 = player2.nextHand()
        if nextHand1.isStrongerThan(nextHand2):
            print("Winner:{0}".format(player1))
            player1.win()
            player2.lose()
        elif nextHand2.isStrongerThan(nextHand1):
            print("Winner:{0}".format(player2))
            player1.lose()
            player2.win()
        else:
            print("Even...")
            player1.even()
            player2.even()

    print("Total Result:")
    print(player1)
    print(player2)

if __name__ == '__main__':
    startMain()

(5) Andere

Verwalte den Sieg oder die Niederlage von Janken.

strategy/hand.py


class Hand(object):
    HANDVALUE_GUU = 0
    HANDVALUE_CHO = 1
    HANDVALUE_PAA = 2
    name = ["Schmiere", "Choki", "Par"]
    hands = []

    def __init__(self, handvalue):
        self.__handvalue = handvalue

    @classmethod
    def getHand(cls, handvalue):
        return cls.hands[handvalue]

    def isStrongerThan(self, hand):
        return self.fight(hand) == 1

    def isWeakerThan(self, hand):
        return self.fight(hand) == -1

    def fight(self, hand):
        if self == hand:
            return 0
        elif (self.__handvalue + 1) % 3 == hand.__handvalue:
            return 1
        else:
            return -1

#    def toString(self):
#        return self.name[self.__handvalue]


Hand.hands.append(Hand(Hand.HANDVALUE_GUU))
Hand.hands.append(Hand(Hand.HANDVALUE_CHO))
Hand.hands.append(Hand(Hand.HANDVALUE_PAA))

■ Referenz-URL

Recommended Posts

Lernen Sie das Entwurfsmuster "Strategie" mit Python
Lernen Sie das Entwurfsmuster "Prototype" mit Python
Lernen Sie das Entwurfsmuster "Builder" mit Python
Lernen Sie das Entwurfsmuster "Observer" in Python
Lernen Sie das Entwurfsmuster "Proxy" in Python
Lernen Sie das Entwurfsmuster "Befehl" in Python
Lernen Sie das Entwurfsmuster "Besucher" mit Python
Lernen Sie das Entwurfsmuster "Bridge" mit Python
Lernen Sie das Entwurfsmuster "Mediator" mit Python
Lernen Sie das Designmuster "Decorator" mit Python
Lernen Sie das Entwurfsmuster "Composite" mit Python
Lernen Sie das Entwurfsmuster "State" in Python
Lernen Sie das Entwurfsmuster "Adapter" mit Python
Lernen Sie das Entwurfsmuster "Abstract Factory" mit Python
Lernen Sie das Entwurfsmuster "Vorlagenmethode" in Python
Lernen Sie das Entwurfsmuster "Factory Method" in Python
Lernen Sie das Entwurfsmuster "Chain of Responsibility" in Python
Lernen Sie das Entwurfsmuster "Singleton" mit Python
Lernen Sie das Designmuster "Facade" mit Python
Implementieren Sie das Singleton-Muster in Python
Singleton-Muster in Python
Entwurfsmuster in Python: Einführung
Python Design Pattern - Template-Methode
Abrufen der arXiv-API in Python
Python im Browser: Brythons Empfehlung
Speichern Sie die Binärdatei in Python
Holen Sie sich den Desktop-Pfad in Python
Holen Sie sich den Skriptpfad in Python
Im Python-Befehl zeigt Python auf Python3.8
Ich habe die Warteschlange in Python geschrieben
Berechnen Sie den Vormonat in Python
Untersuchen Sie die Klasse eines Objekts mit Python
Holen Sie sich den Desktop-Pfad in Python
Holen Sie sich den Hostnamen in Python
Greifen Sie mit Python auf die Twitter-API zu
Der erste Schritt von Python Matplotlib
Ich habe den Stack in Python geschrieben
Beherrsche das schwache Ref-Modul in Python
Lernen Sie die Grundlagen von Python ① Grundlegende Anfänger
Laden Sie das Remote-Python-SDK mit IntelliJ
Versuchen Sie es mit der Wunderlist-API in Python
Überprüfen Sie das Verhalten des Zerstörers in Python
[Python Kivy] Über das Ändern des Designthemas
Versuchen Sie, die Kraken-API mit Python zu verwenden
Schreiben Sie den Test in die Python-Dokumentzeichenfolge
Nehmen Sie die logische Summe von List in Python (Zip-Funktion)
GoF-Entwurfsmuster aus dem Problem 2. Struktur
Zeigen Sie Python 3 im Browser mit MAMP an
Tweet mit der Twitter-API in Python
Überprüfen Sie, ob die URL in Python vorhanden ist
Führen Sie den Python-Interpreter im Skript aus
Das Ergebnis der Installation von Python auf Anaconda
Was ist "Mahjong" in der Python-Bibliothek? ??
Lesen Sie die Datei Zeile für Zeile mit Python
Lesen Sie die Datei Zeile für Zeile mit Python
GoF-Entwurfsmuster aus dem Problem 1. Generation
MongoDB mit Python zum ersten Mal