Cet article est un mémo d'étude personnel. J'écris un article motivé par l'obsession que ce que j'entre doit être une sortie. J'écris cet article sur Qiita avec l'espoir que quelqu'un qui le connaît pourra signaler les erreurs et donner des conseils.
Je vis une vie professionnelle en tant qu'ingénieur, mais je n'ai pas bien appris les modèles de conception, alors j'ai essayé d'étudier.
Ce qui est décrit ici https://github.com/ck-fm0211/notes_desigh_pattern Je télécharge sur.
J'ai étudié les modèles de conception (mémo personnel) Partie 1 J'ai étudié les modèles de conception (mémo personnel) Partie 2 J'ai étudié les modèles de conception (mémo personnel) Partie 3
car.add_tire(CarTire());
car.add_handle(CarHandle());
――Il peut arriver qu'un pneu différent (pneu de vélo) soit remis en raison d'une erreur du programmeur.
car.add_tire(BicycleTire());
car.add_handle(CarHandle());
--Il est possible d'utiliser un objet qui ne doit pas être utilisé
―― Pensez à faire un "pot"
# -*- coding:utf-8 -*-
class HotPot:
pot = None
soup = None
protein = None
vegetables = []
other_ingredients = []
@staticmethod
def hot_pot(pot):
HotPot.pot = pot
@staticmethod
def add_soup(soup):
HotPot.soup = soup
@staticmethod
def add_main(protein):
HotPot.protein = protein
@staticmethod
def add_vegitables(vegitables):
HotPot.vegetables = vegitables
@staticmethod
def add_other_ingredients(other_ingredients):
HotPot.other_ingredients = other_ingredients
--Préparer une classe Factory qui résume le processus de fabrication d'un pot
class Factory(metaclass=ABCMeta):
@abstractmethod
def get_soup(self):
pass
@abstractmethod
def get_main(self):
pass
@abstractmethod
def get_vegetables(self):
pass
@abstractmethod
def get_other_ingredients(self):
pass
--Préparez la classe Mizutaki Factory qui hérite de cela et fabriquez un cuiseur à eau sur cette base.
class MizutakiFactory(Factory):
def get_soup(self):
return "torigara"
def get_main(self):
return "chicken"
def get_vegetables(self):
return ["hakusai", "ninjin", "negi"]
def get_other_ingredients(self):
return ["tofu"]
class Sample:
@staticmethod
def main():
hp = HotPot()
mf = MizutakiFactory()
hp.add_soup(mf.get_main())
hp.add_main(mf.get_main())
hp.add_vegitables(mf.get_vegetables())
hp.add_other_ingredients(mf.get_other_ingredients())
--Sélectionnez et générez la classe Factory à utiliser réellement en fonction de la chaîne de caractères donnée dans l'argument
class Sample:
@staticmethod
def create_factory(s):
if s == "fondue au kimchi":
return KimuchiFactory()
elif s == "Sukiyaki":
return SukiyakiFactory()
else:
return MizutakiFactory()
@staticmethod
def main(arg):
hp = HotPot()
fc = create_factory(arg)
hp.add_soup(fc.get_main())
hp.add_main(fc.get_main())
hp.add_vegitables(fc.get_vegetables())
hp.add_other_ingredients(fc.get_other_ingredients())
--Dans la méthode principale, le traitement se poursuit sans connaître le type réel de la méthode Factory. En d'autres termes, nous procédons au traitement en utilisant la classe abstraite Factory. ――Il est possible de répondre à la demande de "remplacer en douceur les objets à utiliser"
# -*- coding:utf-8 -*-
from abc import ABCMeta, abstractmethod
class Sorter(metaclass=ABCMeta)
@abstractmethod
def sort(self, obj):
pass
class QuickSorter(Sorter):
def sort(self, obj):
#Tri rapide
pass
class BubbleSorter(Sorter):
def sort(self, obj):
#Tri à bulles
pass
--Je veux ajouter une méthode timer_sorter qui a une fonction pour afficher le temps pris pour le tri dans la classe Sorter.
from datetime import datetime
class TimerSorter(metaclass=ABCMeta, Sorter):
@abstractmethod
def time_sorter(self, obj):
start = datetime.now()
Sorter.sort(obj)
end = datetime.now()
print("time:" + str((end - start)))
class SortImple(metaclass=ABCMeta):
@abstractmethod
def sort(self, obj):
pass
class Sorter:
si = SortImple()
@staticmethod
def sorter(si):
Sorter.si = si
def sort(self, obj):
Sorter.si.sort(obj)
class QuickSorterImple(SortImple):
def sort(self, obj):
#Tri rapide
pass
class BubbleSorterImple(SortImple):
def sort(self, obj):
#Tri à bulles
pass
from datetime import datetime
class TimerSorter(metaclass=ABCMeta, Sorter):
def __init__(self, sort_impl):
super(sort_impl)
@abstractmethod
def time_sorter(self, obj):
start = datetime.now()
Sorter.sort(obj)
end = datetime.now()
print("time:" + str((end - start)))
――Lors de la programmation normale, l'algorithme peut être implémenté sous une forme qui se fond dans la méthode. --Changez l'algorithme en branchant avec l'instruction if, etc. --Dans le modèle Stratégie, soyez conscient de la partie stratégie et créez-la en tant que classe distincte. --Créez la partie stratégie x en tant que classe distincte, et si vous souhaitez modifier la stratégie, changez la classe de stratégie à utiliser.
――Il existe de nombreux cas où vous devez changer l'algorithme en fonction de la situation. Par exemple, dans un programme de jeu, l'algorithme de stratégie est modifié en fonction du niveau de difficulté. «Ici, pensons à un algorithme qui fait une simple comparaison entre les grands et les petits.
# -*- coding:utf-8 -*-
from abc import ABCMeta, abstractmethod
class Human:
def __init__(self, name, height, weight, age):
self.name = name
self.height = height
self.weight = weight
self.age = age
class SampleClass:
@staticmethod
def compare(h1: Human, h2: Human) -> int:
if h1.age > h2.age:
return 1
elif h1.age == h2.age:
return 0
else:
return -1
class SampleClass2:
type = -1
COMPARE_AGE = 1
COMPARE_HEIGHT = 2
COMPARE_WEIGHT = 3
def __init__(self, type):
SampleClass2.type = type
@staticmethod
def compare(h1: Human, h2: Human) -> int:
if SampleClass2.type == SampleClass2.COMPARE_AGE:
if h1.age > h2.age:
return 1
elif h1.age == h2.age:
return 0
else:
return -1
elif SampleClass2.type == SampleClass2.COMPARE_HEIGHT:
if h1.height > h2.height:
return 1
elif h1.height == h2.height:
return 0
else:
return -1
#・ ・ ・
――Cela devient un code compliqué. Dans le modèle Stratégie, la partie de l'algorithme qui doit être modifiée en fonction de la situation est consciemment séparée en une classe distincte pour améliorer la perspective de modifier ou d'ajouter l'algorithme.
class AgeComparator:
@staticmethod
def compare(h1: Human, h2: Human) -> int:
if h1.age > h2.age:
return 1
elif h1.age == h2.age:
return 0
else:
return -1
--Séparez la partie de l'algorithme de comparaison afin que le processus de comparaison réel puisse être délégué à AgeComparator.
class MyClass:
@staticmethod
def compare(h1: Human, h2: Human) -> int:
return AgeComparator.compare(h1, h2)
«Cela seul n'a aucun mérite et ce n'est pas un modèle de stratégie. Le modèle de stratégie nécessite que des parties d'algorithme distinctes aient une interface commune.
class Comparator(metaclass=ABCMeta):
@staticmethod
@abstractmethod
def compare(h1: Human, h2: Human) -> int:
pass
class AgeComparator(Comparator):
@staticmethod
def compare(h1: Human, h2: Human) -> int:
if h1.age > h2.age:
return 1
elif h1.age == h2.age:
return 0
else:
return -1
class HeightComparator(Comparator):
@staticmethod
def compare(h1: Human, h2: Human) -> int:
if h1.height > h2.height:
return 1
elif h1.height == h2.height:
return 0
else:
return -1
class SampleClass:
def __init__(self, comp: Comparator):
self._comp = comp
def compare(self, h1: Human, h2: Human) -> int:
return self._comp.compare(h1, h2)
Recommended Posts