Una fábrica es una clase para construir otros objetos, donde crea y devuelve un objeto basado en los parámetros pasados. Aquí, el cliente proporciona materiales a la clase Factory, y la clase Factory crea y devuelve los productos en función del material dado. Una fábrica no es un patrón de diseño, pero sirve como base para el patrón de diseño del método de fábrica.
Antes de entrar en el patrón de diseño del método de fábrica, creemos una fábrica simple . En el siguiente ejemplo, la clase SimpleFactory tiene un método estático llamado build_connection() para crear objetos basados en el parámetro recibido.
Python3
import http.client from ftplib import FTP class SimpleFactory(object): @staticmethod def build_connection(protocol): if protocol == 'https': return http.client.HTTPSConnection('www.python.org') elif protocol == 'ftp': return FTP('ftp1.at.proftpd.org') else: raise RuntimeError('Unknown protocol') if __name__ == '__main__': input_protocol = input('Which protocol to use? (https or ftp):') protocol = SimpleFactory.build_connection(input_protocol) if input_protocol == 'https': protocol.request("GET", "/") resp = protocol.getresponse() print(resp.status, resp.reason) elif input_protocol == 'ftp': resp = protocol.login() print(resp)
Veamos la salida
Aquí, proporciona el tipo de protocolo como argumento, y la clase de fábrica crea y devuelve el objeto en función del argumento. El punto a tener en cuenta es que la creación de objetos no es responsabilidad del cliente.
Patrón de diseño de método de fábrica
El patrón de diseño de método de fábrica es idéntico a una fábrica simple, pero su estructura es complicada en comparación con una estructura de fábrica simple. Tiene una clase abstracta que contiene métodos de fábrica (para crear objetos) y métodos de operación (para trabajar con objetos creados). Y las clases concretas que crean objetos se derivan de la clase abstracta.
Este patrón ayuda a definir una interfaz para crear un objeto. Aquí, las clases que implementan la interfaz deciden qué clase instanciar. Por lo tanto, los métodos de operación en la clase abstracta no necesitan preocuparse por la creación de objetos hasta que se implemente la interfaz del producto.
Nota: si es un principiante, le recomiendo encarecidamente que siga el Método de fábrica: patrones de diseño de Python .
Ventajas del patrón de diseño del método de fábrica
Veamos las ventajas del patrón de diseño de fábrica. Algunos de ellos son:
- Hace que el código sea más universal.
- Separa las interfaces de la implementación.
- Reduce la complejidad del mantenimiento del código.
Acceso a recursos web utilizando un protocolo diferente
Implementemos un programa para acceder a recursos web utilizando el protocolo HTTP o FTP. Aquí, usaremos el sitio ftp.freebsd.org que permite tanto el protocolo HTTP como el FTP.
Del diagrama anterior, podemos entender que el diseño tiene una clase abstracta llamada Conector y dos clases concretas: HTTPConnector y FTPConnector. Las dos clases concretas se derivan de la clase Connector y los métodos de fábrica de la clase abstracta utilizan estas clases para la creación de productos. Veamos el código a continuación.
Python3
import abc import urllib import urllib.error import urllib.request from bs4 import BeautifulSoup class Connector(metaclass=abc.ABCMeta): def __init__(self, is_secure): self.is_secure = is_secure self.port = self.factory_port() self.protocol = self.factory_protocol() @abc.abstractmethod def crawl(self): pass def scan(self, con_domain, con_path): url = self.protocol + '://'+ con_domain \ + ':' + str(self.port) + con_path print(url) return urllib.request.urlopen(url, timeout=10).read() @abc.abstractmethod def factory_protocol(self): pass @abc.abstractmethod def factory_port(self): pass class HTTPConnector(Connector): """ Creates an HTTP Connector """ def factory_protocol(self): if self.is_secure: return 'https' return 'http' def factory_port(self): if self.is_secure: return '443' return '80' def crawl(self, data): """ crawls web content """ filenames = [] soup = BeautifulSoup(data,"html.parser") links = soup.table.findAll('a') for link in links: filenames.append(link['href']) return '\n'.join(filenames) class FTPConnector(Connector): def factory_protocol(self): return 'ftp' def factory_port(self): return '21' def crawl(self, data): # converting byte to string data = str(data, 'utf-8') lines = data.split('\n') filenames = [] for line in lines: extract_line = line.split(None, 8) if len(extract_line) == 9: filenames.append(extract_line[-1]) return '\n'.join(filenames) if __name__ == "__main__": con_domain = 'ftp.freebsd.org' con_path = '/pub/FreeBSD/' con_protocol = input('Choose the protocol \ (0-http, 1-ftp): ') if con_protocol == '0': is_secure = input('Use secure connection? (1-yes, 0-no):') if is_secure == '1': is_secure = True else: is_secure = False connector = HTTPConnector(is_secure) else: is_secure = False connector = FTPConnector(is_secure) try: data = connector.scan(con_domain, con_path) except urllib.error.URLError as e: print('Cannot access resource with this method', e) else: print(connector.crawl(data))
En este programa nos conectamos a una página web mediante el protocolo HTTP o FTP. La clase abstracta Connector está diseñada para establecer una conexión ( método de escaneo ) y también para rastrear las páginas ( método de rastreo ). Además de esto, proporciona dos métodos de fábrica, factory_protocol y factory_port , para manejar el protocolo y la dirección del puerto.
Echemos un vistazo a la salida.
Resumen
Una clase de fábrica se usa para crear otras clases. Hace que el código sea más universal. Los métodos de fábrica en las clases de fábrica actúan como una interfaz para crear un objeto, por lo que separan la interfaz de la implementación. Como resultado, las clases pueden implementar estos métodos de interfaz y pueden decidir qué clase instanciar.
Publicación traducida automáticamente
Artículo escrito por SonuGeorge y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA