Notas sobre patrones de diseño de Java para principiantes: patrón de prototipo

El modo prototipo también se denomina modo modelo original.

 

1. Propósito:
utilizar instancias de prototipos para especificar los tipos de objetos que se crearán y crear nuevos objetos copiando estos prototipos.

 

2. Participantes:
•Prototipo abstracto (Prototipo): declara una interfaz que se clona a sí misma.
•Prototipo Concreto: implementa una operación de clonación del mismo.
• Cliente: permite que un prototipo se clone a sí mismo para crear un nuevo objeto.

 

3. Estructura:



 

 

Por definición, el patrón prototipo se utiliza para copiar objetos.

 

Entonces, ¿cuándo deberías utilizar el modo prototipo?

 

Usemos el ejemplo de la producción de automóviles para entenderlo. 

En primer lugar, según la definición, el modo prototipo necesita clonarse a sí mismo , lo que significa que debe haber un prototipo de producto.

En otras palabras, el prototipo en el patrón de prototipo aún debe crearse primero mediante el método de fábrica u otros métodos.

 

Desde este punto de vista, el patrón prototipo se utiliza cuando se producen múltiples objetos de producto idénticos o similares.

 

Entonces, ¿cuáles son las ventajas de utilizar un patrón prototipo?

 

Suponiendo que se produzca un Audi A6, considere usar el modo de fábrica (o incluso el modo de constructor).

 

1. Si tengo un Audi A6, lo cual es muy bueno, y mi amigo también quiere uno, pero no sabemos en qué fábrica lo produce y no sabemos dónde comprarlo. Si pudiera hacer una copia de mi Audi A6, sería muy conveniente para mis amigos y ni siquiera tendrían que gastar dinero. (¡¡Este es un dulce sueño!!)

Usando el modo prototipo, simplemente clónelo.

De esta manera, no es necesario saber en qué fábrica se produce el producto, simplemente cópielo y rápidamente podrá tener un nuevo objeto de producto.

Esto hace que el sistema sea más independiente de la creación, composición y presentación del producto . Porque se crea por sí mismo para realizar el producto en sí.

 

2. Si necesitas reproducir otros modelos de coches, como el Audi A8.

En modo de fábrica, normalmente necesitamos construir otro Audi A8 de fábrica.

 

Debido a que Audi A8 y Audi A6 tienen el mismo nivel de producto, si clona un objeto de producto Audi A6 y modifica algunos atributos, puede crear un nuevo objeto de producto Audi A8. De esta forma, no se necesitan nuevas fábricas. (¡¡Los fabricantes también sueñan!!)

Es decir, esto evita la creación de una jerarquía de clases de fábrica paralela a la jerarquía de clases de productos.

 

 

 Debido al uso del modo prototipo, el proceso de creación del producto es más independiente y no requiere una clase de fábrica correspondiente, sino que se crea utilizando métodos dentro del producto. Por lo tanto, es más fácil agregar dinámicamente nuevas categorías de productos y reducir las categorías de productos originales sin afectar la estructura del sistema original.

 

 

¿Cómo implementar el modo prototipo?

Se trata de realizar la autorreplicación (clonación) del prototipo. Esto implica los conceptos de clonación superficial y clonación profunda: (Extraído de "Java and Patterns" de Yan Hong)

1. Copia superficial (clon superficial)
Todas las variables del objeto copiado contienen los mismos valores que el objeto original y todas las referencias a otros objetos aún apuntan al objeto original. En otras palabras, una copia superficial sólo copia el objeto en cuestión, no los objetos a los que hace referencia.

2. Copia profunda (clon profundo)
todas las variables del objeto copiado contienen los mismos valores que el objeto original, excepto aquellas variables que hacen referencia a otros objetos. Las variables que hacen referencia a otros objetos apuntarán a los nuevos objetos copiados, en lugar de a los objetos originales a los que se hace referencia. En otras palabras, la copia profunda copia todos los objetos a los que hace referencia el objeto que se va a copiar.

 

3. El proceso de utilizar la serialización para realizar una copia profunda
y escribir objetos en la secuencia es el proceso de serialización, pero en el círculo de programadores de Java, también se le llama muy vívidamente proceso de "congelación" o "decapado". ; La paralelización ( El proceso de deserialización) de lectura de objetos de la secuencia se denomina proceso de "descongelación" o "deselección". Cabe señalar que lo que está escrito en la secuencia es una copia del objeto, y el objeto original todavía existe en la JVM, por lo que lo que se "encurte en pepinillos" es solo una copia del objeto, y los pepinillos de Java pueden todavía estar fresco.
Para realizar una copia profunda de un objeto en el lenguaje Java, a menudo primero puede hacer que el objeto implemente la interfaz serializable, luego escribir el objeto (en realidad solo una copia del objeto) en una secuencia (encurtirlo en un pepinillo) y luego leerlo. (regrese el pepinillo al arroyo) fresco), el objeto puede ser reconstruido.

 

Método clone() de Java:
el método clone copia una copia del objeto y se la devuelve a la persona que llama. En términos generales, el método clone() satisface:
① Para cualquier objeto x, existe x.clone() !=x// El objeto clonado no es el mismo objeto que el objeto original
② Para cualquier objeto x, existe x. clone ().getClass()= =x.getClass()//El objeto clonado tiene el mismo tipo que el objeto original
③ Si el método equals() del objeto x está definido correctamente, entonces x.clone().equals( x) debería ser cierto.

Clonación de objetos en Java
① Para obtener una copia del objeto, podemos utilizar el método clone() de la clase Object.
② Anule el método clone() de la clase base en la clase derivada y declarelo como público.
③En el método clone() de la clase derivada, llame a super.clone().
④Implemente la interfaz Cloneable en la clase derivada.

 

Código implementado en Java:

Copia superficial (clon superficial):

Categoría de automóvil:

 

/*
 * 汽车类
 * 
 * 浅克隆(shadow clone)的实现
 */
public class Car implements Cloneable {
	
//	汽车款式
	public int type;

//	引用的其他对象,汽车发动机
	public Engine engine;

	public Object clone() {
		
		Object clone = null;
		try {

//			这里只是克隆的自己本身
			clone = super.clone();
			
//			为什么在派生类中覆盖Object的clone()方法时,一定要调用super.clone()呢?
//			因为,在运行时刻,Object中的clone()识别出你要复制的是哪一个对象,然后为此对象分配空间,并进行对象的复制,
//			将原始对象的内容一一复制到新对象的存储空间中。	
			
		} catch (CloneNotSupportedException e) {

		}
		return clone;
	}

}

 

Tipo de motor:

/*
 * 汽车发动机类,汽车类中引用的对象的类
 */
public class Engine implements Cloneable {
	
//	汽车发动机型号
	public int model;

}

 

Llamada del cliente:

/*
 * 浅克隆(shadow clone)的调用
 */
public class Client {
	   public static  void main(String argv[])
	   {
		 System.out.println("-----创建汽车1-----");
		 Car car1=new Car();
	     car1.engine=new Engine();
	     car1.type=1;
	     car1.engine.model=1;
	     System.out.println("汽车1款式:"+car1.type+"\t汽车1的发动机型号:"+car1.engine.model);
	     
	     System.out.println("----汽车1--克隆-->汽车2----");
	     Car car2=(Car)car1.clone();
	     car2.type=2;
	     car2.engine.model=2;
	     
	     System.out.println("汽车2款式:"+car2.type+"\t汽车2的发动机型号:"+car2.engine.model);
	     System.out.println("汽车1款式:"+car1.type+"\t汽车1的发动机型号:"+car1.engine.model);
	   }
	 }

 

resultado de la operación:

-----创建汽车1-----
汽车1款式:1	汽车1的发动机型号:1
----汽车1--克隆-->汽车2----
汽车2款式:2	汽车2的发动机型号:2
汽车1款式:1	汽车1的发动机型号:2

 

Según los resultados de la ejecución, se puede encontrar que la copia superficial (clon superficial) solo copia el objeto considerado, pero no el objeto al que se refiere. Por lo tanto, cuando el modelo de motor del automóvil 2
se establece en 2 , el modelo de motor del automóvil 1 también cambia de 1 a 2 .

Porque el coche 1 y el coche 2 en realidad utilizan el mismo motor.

 

Copia profunda (clon profundo):

¿Cómo implementar la copia profunda (clonación profunda)? Modifique la clase de automóvil y la clase de motor del automóvil:

 

Categoría de automóvil:

/*
 * 深克隆
 */
public class Car implements Cloneable {
	
	public int type;

//	引用的其他对象
	public Engine engine;

	public Object clone() {

		Car temp = null;
		try {

//			先把自己本身复制
			temp = (Car) super.clone();
			
//			为了实现深度克隆,需要将对其他对象(在这里是engine)的引用都复制过去。
			temp.engine = (Engine) engine.clone();
		} catch (CloneNotSupportedException e) {
			// should never happen
		}

		return temp;
	}
}

 

Tipo de motor:

public class Engine implements Cloneable {
	public int model;

	/**
	 * 为了实现深度克隆,需要给在Lay1中被应用的对象lay2)也提供一个自己克隆自身的方法
	 */
	public Object clone() {
		Object clone = null;
		try {
			clone = super.clone();
		} catch (CloneNotSupportedException e) {

		}
		return clone;
	}

}

 

Las llamadas de los clientes permanecen sin cambios.

 

resultado de la operación:

-----创建汽车1-----
汽车1款式:1	汽车1的发动机型号:1
----汽车1--克隆-->汽车2----
汽车2款式:2	汽车2的发动机型号:2
汽车1款式:1	汽车1的发动机型号:1

 

Según los resultados de la ejecución, se puede encontrar que la copia profunda (clonación profunda) copia todos los objetos a los que hace referencia el objeto que se va a copiar.

Por lo tanto, cuando el modelo de motor del automóvil 2 se establece en 2 , el modelo de motor del automóvil 1 sigue siendo 1, sin cambios .

Porque el coche 1 y el coche 2 tienen dos motores diferentes.

 

Utilice la serialización para realizar una copia profunda (clon profundo):

 

Automóvil

Implementó la interfaz de serialización y utilizó objetos de lectura y escritura en secuencias.

 

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

/*
 * 汽车类
 * 
 * 序列化的方式实现深克隆(deep clone)
 */
public class Car implements Serializable {

	/**
	 * serialVersionUID 
	 */
	private static final long serialVersionUID = 1859639569305572020L;

//	汽车款式
	public int type;

//  引用的其他对象,汽车发动机
	public Engine engine;

	public Object clone() {

		try {

//			将对象写到流里,把对象写到流里的过程是串行化(Serilization)过程

			ByteArrayOutputStream bo = new ByteArrayOutputStream();
			ObjectOutputStream oo;

			oo = new ObjectOutputStream(bo);

			oo.writeObject(this);

//			从流里读出来,把对象从流中读出来的并行化(Deserialization)过程
			ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
			ObjectInputStream oi = new ObjectInputStream(bi);
			return (oi.readObject());

		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			return null;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			return null;
		}
	}
}

 

 

Categoría de motor de automóvil:

 

import java.io.Serializable;

public class Engine implements Cloneable, Serializable {

	/**
	 * Car对象以及对象内部所有引用到的对象engine都是可串行化的
	 */
	private static final long serialVersionUID = -6228724315977120960L;

	public int model;

}

 

 

Las llamadas de los clientes permanecen sin cambios.

 

resultado de la operación:

-----创建汽车1-----
汽车1款式:1	汽车1的发动机型号:1
----汽车1--克隆-->汽车2----
汽车2款式:2	汽车2的发动机型号:2
汽车1款式:1	汽车1的发动机型号:1

 

Según los resultados de la ejecución, se puede encontrar que la copia profunda (clonabilidad) también se logra mediante la serialización.

Por lo tanto, cuando el modelo de motor del automóvil 2 se establece en 2 , el modelo de motor del automóvil 1 sigue siendo 1, sin cambios .

Porque el coche 1 y el coche 2 tienen dos motores diferentes.

Supongo que te gusta

Origin blog.csdn.net/louis_lee7812/article/details/83778148
Recomendado
Clasificación