J'ai pratiqué les modèles de conception afin de pouvoir écrire du code conscient du design. D'autres modèles de conception seront publiés fréquemment.
L'objectif principal est de comprendre quand, quoi et comment utiliser les modèles de conception. (Je suis nouveau en Java ou dans un langage à typage statique, et je n'ai pas une longue histoire de python, donc je pense qu'il y a des choses qui ne ressemblent pas à Pythonista. Si vous avez des suggestions, apprenez-moi s'il vous plaît.)
Cette fois, le motif Proxy était lié à la structure.
Préparez un proxy pour contrôler la création d'instances et les restrictions d'accès, et demandez au proxy de faire le travail jusqu'à ce qu'il soit nécessaire. Cependant, lorsque l'agent dépasse la plage qui peut être effectuée, l'agent donne le rôle à la personne d'origine.
Cet exemple de programme est une «imprimante nommée». La classe Main crée une instance de classe (agent) pour PrinterProxy. Nommez l'instance «Alice» et affichez le nom. Puis renommez-le en "Bob" et affichez ce nom.
En définissant ou en obtenant le nom, nous n'avons pas encore créé d'instance (personne) de la classe d'imprimante réelle. La classe PrinterProxy prend en charge la partie de la configuration et de l'obtention du nom. Enfin, la classe PrinterProxy crée une instance de la classe Printer uniquement lorsqu'il est temps d'appeler la méthode my_print et d'imprimer réellement.
Une interface appelée Printable est définie pour assimiler la classe PrinterProxy à la classe Printer. Ici, l'exemple de programme est créé en supposant qu'il faut beaucoup de temps pour instancier la classe Printer. Afin d'exprimer que cela prend du temps, j'appelle une méthode appelée heavy_job du constructeur et gagne quelques secondes en tant que "traitement lourd".
printer.py
import sys
import time
from printable import Printable
class Printer(Printable):
def __init__(self, name):
self.__name = name
self.__heavy_job('Instance d'imprimante({0})Est en cours de génération'.format(self.__name))
def set_printer_name(self, name):
self.__name = name
def get_printer_name(self):
return self.__name
def my_print(self, string):
print('===' + ' ' + self.__name + ' ' + '===')
print(string)
def __heavy_job(self, msg):
sys.stdout.write(msg)
for i in range(1, 5):
try:
time.sleep(1)
except InterruptedError:
pass
sys.stdout.write('.')
print('Terminé.')
La classe Printer est une classe qui représente «la personne». Je fais du heavy_job comme un "gros travail".
Après cela, il y a set_printer_name pour définir le nom, get_printer_name pour obtenir le nom et my_print pour afficher la chaîne de caractères. Le centre du modèle Proxy est vers la classe PrinterProxy.
printable.py
from abc import abstractmethod
class Printable():
@abstractmethod
def set_printer_name(self, name):
pass
@abstractmethod
def get_printer_name(self):
pass
@abstractmethod
def my_printer(self, string):
pass
L'interface imprimable sert à assimiler la classe PrinterProxy à la classe Printer.
printer_proxy.py
from printable import Printable
from printer import Printer
class PrinterProxy(Printable):
def __init__(self, name):
self.__name = name
self.__real = None
def set_printer_name(self, name):
if (self.__real is not None):
self.__real.set_printer_name(name)
self.__name = name
def get_printer_name(self):
return self.__name
def my_print(self, string):
self.__realize()
self.__real.my_print(string)
def __realize(self):
if (self.__real is None):
self.__real = Printer(self.__name)
La classe PrinterProxy agit comme un agent. Implémente l'interface imprimable. Le champ du nom sert à contenir le nom et le champ réel sert à contenir la «personne».
Dans le constructeur, définissez le nom. La méthode set_printer_name définit un nouveau nom. Si real n'est pas None, définissez également le nom de la personne. Toutefois, si real est None, il renvoie une valeur dans le champ de nom PrinterProxy.
Puisque la méthode my_print est un processus en dehors de la portée de cet agent, appelez la méthode de réalisation pour générer la "personne". Après avoir exécuté la méthode de réalisation, le champ réel contient la personne, appelez donc real.print. C'est la "délégation".
** Peu importe le nombre de fois que vous appelez set_printer_name ou get_printer_name, l'imprimante ne sera pas instanciée. Aucune instance d'imprimante n'est créée. ** Une instance d'imprimante est créée uniquement lorsque la "personne" est nécessaire. (Les utilisateurs de PrinterProxy ne savent pas du tout si la personne a été générée et il n'y a pas lieu de s'en inquiéter.)
La méthode de réalisation crée une instance d'imprimante si le champ réel est Aucun. Si le champ réel n'est pas None, ne faites rien.
main.py
from printer_proxy import PrinterProxy
def main():
pp = PrinterProxy('Alice')
print('Le nom est maintenant' + pp.get_printer_name() + 'est.')
pp.set_printer_name('Bob')
print('Le nom est maintenant' + pp.get_printer_name() + 'est.')
pp.my_print('Hello, world.')
if __name__ == '__main__':
main()
Résultat d'exécution
Le nom est maintenant Alice.
Le nom est maintenant Bob.
Instance d'imprimante(Bob)Est en cours de génération....Terminé.
=== Bob ===
Hello, world.
Dans le modèle Proxy, le rôle Proxy agit comme un agent et prend en charge le traitement autant que possible. Dans l'exemple de programme, en utilisant le rôle Proxy, il était possible de retarder le traitement intensif (instanciation) jusqu'au my_print réel.
S'il y a beaucoup de fonctions qui prennent beaucoup de temps à s'initialiser dans la scène d'utilisation réelle, je pense qu'elles ne seront initialisées que lorsqu'il sera temps d'utiliser réellement ces fonctions. Je pense que c'est l'un des modèles de conception les plus couramment utilisés.
Recommended Posts