En tant que matériel d'apprentissage des modèles de conception du GoF, le livre «Introduction aux modèles de conception appris dans le langage Java augmenté et révisé» semble être utile. Cependant, comme les exemples repris sont basés sur JAVA, j'ai essayé la même pratique avec Python pour approfondir ma compréhension.
Le modèle de stratégie est un modèle de conception dans lequel des algorithmes peuvent être sélectionnés au moment de l'exécution dans le domaine de la programmation informatique. Le modèle de stratégie contient une référence au sous-programme qui décrit l'algorithme à l'intérieur de la structure de données. En plus des pointeurs de fonction, des objets de fonction et des délégués, le polymorphisme et la délégation dans les langages orientés objet orthodoxes ou le typage dynamique de canard par réflexion sont utilisés pour réaliser ce modèle.
UML class and sequence diagram
UML class diagram (Ce qui précède est cité sur Wikipedia)
Le modèle Strategy
sépare délibérément la partie algorithme des autres parties et spécifie uniquement la partie interface avec cet algorithme. Ensuite, l'algorithme est utilisé par délégation du programme.
Lors de l'amélioration du programme, si vous utilisez le modèle Strategy
, veillez à ne pas changer l'interface du rôle Strategy
, il vous suffit de modifier le rôle ConcreteStrategy
, et ** la délégation est une délégation graduelle. Parce qu'il utilise des liens, il permet également de basculer facilement entre les algorithmes **.
En fait, je voudrais essayer d'exécuter un exemple de programme qui utilise le modèle de stratégie et vérifier le comportement suivant. Ici, ** Taro ** et ** Hanako ** seront en compétition pour la victoire ou la défaite en répétant Janken.
La stratégie de Janken
«Si Taro bat Janken, il défiera le prochain Janken avec la même main. --Hanako défie Janken dans l'ordre "Goo", "Choki", "Par"
$ 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]
Le résultat est que la stratégie Janken de ** hanako ** (défier Janken dans l'ordre "goo", "choki", "par") est meilleure que la stratégie Janken de ** Taro **. J'ai fait. C'est parce que la stratégie Janken de ** Taro ** (si vous gagnez le Janken, vous défierez le prochain Janken avec la même main), vous ne pourrez jamais gagner d'affilée.
Un code similaire a été téléchargé dans le référentiel Git. https://github.com/ttsubo/study_of_design_pattern/tree/master/Strategy
.
├── Main.py
└── strategy
├── __init__.py
├── hand.py
├── player.py
└── strategy.py
C'est le rôle qui définit l'interface d'utilisation de la stratégie.
Dans l'exemple de programme, la classe Strategy
remplit ce rôle.
strategy/strategy.py
from abc import ABCMeta, abstractmethod
class Strategy(metaclass=ABCMeta):
@abstractmethod
def nextHand(self):
pass
@abstractmethod
def study(self, win):
pass
C'est le rôle qui implémente en fait l'interface du rôle de «Stratégie». Ici, vous allez effectivement programmer la stratégie spécifique (travail, politique, méthode, algorithme).
Dans l'exemple de programme, la classe WinningStrategy
et la classe CircularStrategy
remplissent ce rôle.
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
C'est un rôle qui utilise le rôle «Stratégie». J'ai une instance du rôle ConcreteStrategy
et je l'utilise si nécessaire.
Dans l'exemple de programme, la classe Player
remplit ce rôle.
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)
Dans l'exemple de programme, la méthode startMain
remplit ce rôle.
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()
Gérez la victoire ou la défaite de Janken.
strategy/hand.py
class Hand(object):
HANDVALUE_GUU = 0
HANDVALUE_CHO = 1
HANDVALUE_PAA = 2
name = ["Goo", "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