Definición: Encapsula ciertas operaciones que actúan en cada elemento en una determinada estructura de datos. Puede definir nuevas operaciones que actúen sobre estos elementos sin cambiar la estructura de datos.
Tipo: Patrón de comportamiento
Diagrama de clases:
ejemplo:
Por ejemplo, piense en agregar diferentes tipos de bienes al carrito, y al hacer clic en el pago, calcula las tarifas que se pagarán por todos los diferentes bienes. Ahora, la lógica de cálculo es calcular los precios de estos diferentes tipos de bienes. O en otras palabras, transferimos esta lógica a otra clase a través del modo de visitante. Implementemos este ejemplo de patrón de visitantes.
Para implementar el patrón de visitantes, lo primero que debe hacer es crear una clase que se pueda agregar al carrito de compras para representar diferentes tipos de elementos (elementos).
ItemElement.javapackage com.journaldev.design.visitor; interfaz pública itemElement {public int Aceptar (compationCartvisitor Visitor);}Tenga en cuenta que el método de aceptación acepta el visitante como parámetro. Por supuesto, hay otras formas de especificar productos detallados aquí, pero por simplicidad, no es necesario considerar demasiados detalles aquí, solo centrándose en el modo de visitante.
Ahora cree algunas clases de entidad para diferentes productos.
Libro.java
paquete com.journaldev.design.visitor; el libro de clase pública implementa itemElement {private int precio; cadena privada isbnnumber; Libro público (int cost, string isbn) {this.price = costo; this.isbnnumber = isbn; } public int getPrice () {Return Price; } public String getisbnnumber () {return isbnnumber; } @Override public int Aceptar (ShoppingCartVisitor Visitor) {return Visitor.Visit (this); }}Fruta.java
paquete com.journaldev.design.visitor; public class Fruit implementa itemElement {private int rayperkg; Peso privado int; nombre de cadena privada; Public Fruit (int Pricekg, int wt, string nm) {this.priceperkg = preciokg; this.weight = wt; this.name = nm; } public int getPricePerkg () {return precioperkg; } public int getPeight () {return peso; } public String getName () {return this.name; } @Override public int Aceptar (ShoppingCartVisitor Visitor) {return Visitor.Visit (this); }} Tenga en cuenta que la implementación del método Accept () está en la clase de entidad, que llama al método visitante del visitante () para pasar el objeto de clase actual como su propio parámetro.
Aquí, el método Visit () utilizado para diferentes tipos de bienes se implementará en la clase de entidad de la interfaz del visitante.
CompationCartVisitor.java
paquete com.journaldev.design.visitor; interfaz pública CompingCartVisitor {int viss (libro de libros); int visit (fruta fruta);}La interfaz del visitante ahora se implementará y la lógica de calcular sus propios gastos para cada producto.
Compras de compra
paquete com.journaldev.design.visitor; public class ShoppingCartVisitorImpl implementa CompingCartVisitor {@Override public int visit (libro de libros) {int cost = 0; // aplica 5 $ descuento si el precio del libro es mayor que 50 if (book.getPrice ()> 50) {cost = book.getPrice ()-5; } else cost = book.getPrice (); System.out.println ("Book isbn ::"+book.getisbnnumber ()+"cost ="+cost); costo de devolución; } @Override public int visit (frutas frutas) {int cost = fruit.getPriceperkg ()*fruit.getWeight (); System.out.println (fruit.getName () + "cost =" + cost); costo de devolución; }}Ahora veamos cómo usarlo en el programa.
CompatingCartClient.java
paquete com.journaldev.design.visitor; public class ShoppingCartClient {public static void main (string [] args) {itemElement [] elementos = new itemElement [] {nuevo libro (20, "1234"), nuevo libro (100, "5678"), nueva fruta (10, 2, "pláana"), nuevo fruto (5, 5, "manzana";}; int total = calculatePrice (elementos); System.out.println ("Costo total ="+total); } private static int calculatePrice (itemElement [] elementos) {ShoppingCartVisitor Visitor = new ShoppingCartVisitorImpl (); int sum = 0; para (itemElement item: elementos) {sum = sum + item.accept (visitante); } suma de retorno; }}Al ejecutar el programa anterior, obtenemos la siguiente salida.
Libro ISBN :: 1234 Costo = 20Book ISBN :: 5678 Costo = 95Banana Costo = 20 Apple Costo = 25 Costo Total = 160
Tenga en cuenta que la implementación aquí parece ser la misma que el método Acept () para todos los productos, pero también puede ser diferente. Por ejemplo, si el producto está vacío, puede realizar comprobaciones lógicas y ya no llama al método Visit ().
Ventajas del modo visitante:
Realice el principio de responsabilidad única: en cualquier escenario en el que el modo de visitante sea aplicable, las operaciones que deben encapsularse en el visitante en la clase de elementos deben ser operaciones que tengan poco que ver con la clase de elementos en sí y son volátiles. Por un lado, el uso del modo de visitante cumple con el principio de responsabilidad única y, por otro lado, porque las operaciones encapsuladas suelen ser volátiles, cuando ocurren cambios, la expansión de la parte cambiante se puede lograr sin cambiar la clase de elementos en sí.
Buena escalabilidad: las clases de elementos pueden extender diferentes operaciones al aceptar diferentes visitantes.
Escenarios aplicables para el modo de visitante:
Si hay algunas operaciones en un objeto que no están relacionados con el objeto (o débilmente relacionados) y para evitar estas operaciones que contaminan el objeto, puede usar el modo de visitante para encapsular estas operaciones en el visitante.
Si hay operaciones similares en un grupo de objetos, para evitar una gran cantidad de código duplicado, estas operaciones duplicadas también pueden encapsularse en el visitante.
Sin embargo, el modo de visitante no es tan perfecto, y también tiene defectos fatales: agregar nuevas clases de elementos es más difícil. A través del código del patrón de visitantes, podemos ver que en la clase de visitantes, cada clase de elementos tiene su método de procesamiento correspondiente. Es decir, cada clase de elementos debe agregarse para modificar la clase de visitantes (también incluida la clase de subclase o implementación de la clase de visitantes), que es bastante problemático de modificar. Es decir, cuando el número de clases de elementos es incierto, el modo de visitante debe usarse con precaución. Por lo tanto, el modo de visitante es más adecuado para refactorizar las funciones existentes. Por ejemplo, si se han determinado las funciones básicas de un proyecto, los datos de las clases de elementos se han determinado básicamente y no cambiarán. Todo lo que cambiará son las operaciones relevantes dentro de estos elementos. En este momento, podemos usar el modo de visitante para refactorizar el código original, para que las funciones originales puedan modificarse sin modificar cada clase de elemento.
Resumir:
Como GOF, el autor del patrón de diseño, describe el modo de visitante: en la mayoría de los casos, debe usar el modo de visitante, pero una vez que lo necesita, realmente lo necesita. Por supuesto, esto es solo para los verdaderos grandes. En realidad (al menos en el entorno en el que estoy), muchas personas a menudo son adictas a los patrones de diseño. Al usar un patrón de diseño, nunca consideran seriamente si el patrón que están utilizando es adecuado para este escenario, pero a menudo solo quieren mostrar su capacidad para controlar el diseño orientado a objetos. Si tiene esta mentalidad al programar, a menudo abusa del patrón de diseño. Por lo tanto, al aprender patrones de diseño, debe comprender la aplicabilidad de los patrones. Es necesario usar un patrón porque comprende sus ventajas, no usar un patrón porque comprende sus desventajas; En lugar de usar un patrón porque no comprende sus desventajas, no usar un patrón porque no comprende sus ventajas.