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.
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
UML class diagram (Das Obige ist aus Wikipedia zitiert)
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 **.
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.
Ä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
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
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
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)
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()
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))
Recommended Posts