English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Detalles del ejemplo de patrón de diseño de prototipo en programación Android

Este artículo describe el patrón de prototipo en la programación de Android. Comparto con todos para que lo referencien, como se muestra a continuación:

Uno, introducción

El patrón de prototipo es un patrón de creación. Las dos palabras prototipo indican que este modelo debe tener un ejemplo de prototipo, el usuario copia un objeto interno con propiedades idénticas desde este objeto de prototipo, este proceso también es lo que llamamos "clonar". El ejemplo copiado es lo que llamamos "prototipo", este prototipo también es personalizable. El modelo de prototipo se utiliza principalmente para crear instancias complejas o de construcción costosa, porque en este caso, copiar una instancia existente puede hacer que el programa funcione más eficientemente.

Dos, definición

Usar un ejemplo de prototipo para especificar el tipo de objeto a crear y crear nuevos objetos copiando estos prototipos.

Tres, escenarios de uso

(1Al necesitar que la inicialización de la clase consuma muchos recursos, que incluyen datos, recursos de hardware, etc., evitar estos consumos a través de la copia de prototipo.

(2Al necesitar crear un objeto a través de new que requiera una preparación de datos muy compleja o permisos de acceso, en este caso se puede usar el patrón de prototipo.

(3Al necesitar proporcionar un objeto a otros objetos para su acceso y que cada llamador pueda modificar su valor, se puede considerar usar el patrón de prototipo para copiar múltiples objetos para su uso por los llamadores, es decir, copia protectoria.

Es necesario tener en cuenta que, al llamar a la función clone del constructor a través de la interfaz Cloneable del patrón de prototipo, no necesariamente es más rápido que la operación new, solo cuando la creación de objetos a través de new es más costosa o más costosa, el método clone puede obtener una mejora en la eficiencia. Por lo tanto, al usar Cloneable, es necesario considerar el costo de construcción del objeto y realizar algunas pruebas de eficiencia. Por supuesto, la implementación del patrón de prototipo no tiene que implementar la interfaz Cloneable, también hay otras formas de implementación, que se explicarán uno por uno aquí.

Cuatro, diagrama de clase UML del modelo de prototipo

Introducción de personajes en la imagen:

Client: usuario de cliente.

Prototype: clase abstracta o interfaz, que declara la capacidad de clonar.

ConcretePrototype: clase de prototipo específica.

Cinco, implementación simple del patrón de prototipo

A continuación, se toma como ejemplo la copia de un documento simple para demostrar el patrón de prototipo simple. En este ejemplo, primero creamos un objeto de documento, es decir, WordDocument, que contiene texto e imágenes. Después de una larga edición de contenido, el usuario tiene la intención de realizar una edición adicional de este documento, pero no está claro si este documento editado será adoptado, por lo tanto, por seguridad, el usuario necesita hacer una copia del documento actual y luego modificar la copia del documento, lo que es similar al copiado protectorio mencionado en el libro "Effective Java", de esta manera, este documento original es el ejemplo mencionado anteriormente, es decir, el objeto que se va a "clonar", que llamamos prototipo:

Ejemplo de código:

/**
 * 文档类型,扮演的是ConcretePrototype角色,而cloneable是代表prototype角色
 */
public class WordDocument implements Cloneable {
 //Texto
 private String mText;
 //图片名列表
 private ArrayList<String> mImages = new ArrayList<String>();
 public WordDocument(){
  System.out.println("-------- Constructor de WordDocument --------");
 }
 public String getText(){
  return this.mText;
 }
 public void setText(String text){
  this.mText = text;
 }
 public ArrayList<String> getImages(){
  return this.mImages;
 }
 public void setImages(ArrayList<String> images){
  this.mImages = images;
 }
 public void addImage(String img){
  this.mImages.add(img);
 }
 /**
  * 打印文档
  */
 public void showDocument(){
  System.out.println("-------- Inicio del contenido de Word --------");
  System.out.println("Text : " + this.mText);
  System.out.println("Images List : ");
  for(String image : mImages){
   System.out.println("image name : " + image);
  }
  System.out.println("-------- Fin del contenido de Word --------");
 }
 @Override
 protected WordDocument clone(){
  try{
   WordDocument doc = (WordDocument)super.clone();
   doc.mText = this.mText;
   doc.mImages = this.mImages;
   return doc;
  }catch(Exception e){}
  return null;
 }
}

执行方法:

public static void main(String[] args) throws IOException {
  //1.构建文档对象
  WordDocument originDoc = new WordDocument();
  //2.编辑文档,添加图片等
  originDoc.setText("这是一篇文档");
  originDoc.addImage("图片一");
  originDoc.addImage("图片二");
  originDoc.addImage("图片三");
  .addImage("Esta es la imagen nueva añadida");
  //originDoc.addImage("imagen tres");
  copiando una copia de la versión original2 WordDocument doc
  doc2originDoc.showDocument();
  //= originDoc.clone();
  doc2modificación de la copia del documento2.setText("Este es el Doc
  doc2texto");
  .addImage("Esta es la imagen nueva añadida");
  doc2originDoc.showDocument();
}

.showDocument();

-------- Constructor de WordDocument --------
//originDoc
-------- Inicio del contenido de Word --------
Texto: Esto es un documento
Lista de imágenes:
Nombre de imagen: Imagen uno
Nombre de imagen: Imagen dos
Nombre de imagen: Imagen tres
-------- Fin del contenido de Word --------
//doc2
-------- Inicio del contenido de Word --------
Texto: Esto es un documento
Lista de imágenes:
Nombre de imagen: Imagen uno
Nombre de imagen: Imagen dos
Nombre de imagen: Imagen tres
-------- Fin del contenido de Word --------
//Modificación de copia del originDoc
-------- Inicio del contenido de Word --------
Texto: Esto es un documento
Lista de imágenes:
Nombre de imagen: Imagen uno
Nombre de imagen: Imagen dos
Nombre de imagen: Imagen tres
Nombre de imagen: Esta es la imagen nueva añadida
-------- Fin del contenido de Word --------
//Modificación de copia del doc2
-------- Inicio del contenido de Word --------
Texto: Este es el Doc modificado2Texto
Lista de imágenes:
Nombre de imagen: Imagen uno
Nombre de imagen: Imagen dos
Nombre de imagen: Imagen tres
Nombre de imagen: Esta es la imagen nueva añadida
-------- Fin del contenido de Word --------

el resultado de la ejecución:2Aquí descubrimos que al modificar doc

Después de eso, solo afectó a mImages de originDoc, sin cambiar mText.

Seis, copia superficial y copia profunda

la implementación del patrón de prototipo mencionado anteriormente es en realidad una copia superficial, también conocida como copia de sombra, esta copia no reconstituye todos los campos del documento original, sino que los campos del documento secundario se refieren a los campos del documento original, como se muestra en la siguiente figura:2se agregó una imagen, pero también se mostró en originDoc, ¿por qué es así? Los lectores cuidadosos pueden descubrir que los últimos dos documentos tienen información de salida idéntica. En doc++los lectores tendrán una experiencia bastante profunda, ya que en el método clone de WordDocument mencionado anteriormente solo se realizó una copia superficial, el nuevo objeto de tipo referencia doc2.mImages solo apunta a la referencia this.mImages, sin construir un nuevo objeto mImages y agregar las imágenes del documento original al nuevo objeto mImages, lo que lleva a que doc2.mImages es el mismo objeto que el del documento original, por lo que si se modifica una de las imágenes en uno de los documentos, el otro también se verá afectado. ¿Cómo se puede resolver este problema? La respuesta es utilizar una copia profunda, es decir, al copiar el objeto, también se debe copiar el campo de tipo referencia, en lugar de solo referenciar.

Se modifica el método clone de la siguiente manera (otros no se modifican):

@Override
protected WordDocument clone(){
  try{
   WordDocument doc = (WordDocument)super.clone();
   doc.mText = this.mText;
   //También se llama a la función clone() para el objeto mImages, realizando una copia profunda.
   doc.mImages = (ArrayList<String>)this.mImages.clone();
   return doc;
  }catch(Exception e){}
  return null;
}

El resultado de ejecutar el código después de la modificación es:

-------- Constructor de WordDocument --------
//originDoc
-------- Inicio del contenido de Word --------
Texto: Esto es un documento
Lista de imágenes:
Nombre de imagen: Imagen uno
Nombre de imagen: Imagen dos
Nombre de imagen: Imagen tres
-------- Fin del contenido de Word --------
//doc2
-------- Inicio del contenido de Word --------
Texto: Esto es un documento
Lista de imágenes:
Nombre de imagen: Imagen uno
Nombre de imagen: Imagen dos
Nombre de imagen: Imagen tres
-------- Fin del contenido de Word --------
//Modificación de copia del originDoc
-------- Inicio del contenido de Word --------
Texto: Esto es un documento
Lista de imágenes:
Nombre de imagen: Imagen uno
Nombre de imagen: Imagen dos
Nombre de imagen: Imagen tres
-------- Fin del contenido de Word --------
//Modificación de copia del doc2
-------- Inicio del contenido de Word --------
Texto: Este es el Doc modificado2Texto
Lista de imágenes:
Nombre de imagen: Imagen uno
Nombre de imagen: Imagen dos
Nombre de imagen: Imagen tres
Nombre de imagen: Esta es la imagen nueva añadida
-------- Fin del contenido de Word --------

Se puede ver que no afectan mutuamente, lo que se llama copia profunda.

Siguiendo la pregunta anterior, en realidad, el tipo String es similar a los tipos de referencia en la copia superficial, no se replica de forma separada, sino que se refiere al mismo dirección, ya que String no ha implementado el interfaz Cloneable, lo que significa que solo se puede copiar la referencia. (Podemos ver el código fuente para ver que ArrayList ha implementado el interfaz Cloneable) Pero cuando se modifica uno de los valores, se asigna un nuevo bloque de memoria para guardar el nuevo valor, y esta referencia apunta al nuevo espacio de memoria. Dado que el String aún tiene referencias que lo apuntan, no se reciclará. Por lo tanto, aunque es una copia de la referencia, no cambia el valor del objeto copiado cuando se modifica el valor.

Por lo tanto, en muchos casos, podemos tratar a String de la misma manera que a tipos básicos al clonar, solo debemos prestar atención a algunos detalles en el equals.

El patrón de prototipo es muy simple, y su problema central es copiar el objeto original. Al usar este patrón, es necesario prestar atención a un punto: el problema de copia profunda y copia superficial. Durante el desarrollo, para reducir los errores, el autor recomienda usar este patrón y preferir la copia profunda para evitar problemas de influencia en el objeto original al operar con copias.

Siete, Patrón de prototipo en el código fuente de Android

Ejemplo de código:

Uri uri = Uri.parse("smsto:");110");
Intent intent = new Intent(Intent.ACTION_SEND,uri);
intent.putExtra("sms_body", "The SMS text");
//clonación
Intent intent2 = (Intent)intent.clone();
startActivity(intent2);

Ocho, Resumen

El patrón de prototipo es esencialmente una copia de objetos, y es similar a C++La función de constructor de copia de un objeto en chino simplificado es bastante similar, y los problemas que pueden ocurrir entre ellos también son copia profunda y copia superficial. El uso del patrón de prototipo puede resolver el problema de consumo de recursos al construir objetos complejos y puede mejorar la eficiencia de creación de objetos en ciertos escenarios.

Ventajas:

(1) El patrón de prototipo es una copia en binario en la memoria, es mucho más eficiente que crear un objeto directamente mediante new, especialmente cuando se generan muchos objetos dentro de un bucle, el patrón de prototipo puede destacar más sus ventajas.

(2) Otra función importante es la copia protectora, es decir, para un objeto que puede ser de solo lectura desde el exterior, para evitar que el objeto de solo lectura modifique externamente, generalmente se puede implementar la restricción de solo lectura mediante la devolución de una copia del objeto.

Desventajas:

(1) Esto es tanto una ventaja como un inconveniente, copia directamente en la memoria, el constructor no se ejecuta, se debe prestar atención a este problema potencial en el desarrollo real. La ventaja es reducir las restricciones, el inconveniente también es reducir las restricciones, lo que debe considerarse en la aplicación real.

(2El patrón de prototipo no necesariamente es más rápido que la creación de instancias mediante la función clone al llamar al constructor clone, solo cuando la creación de objetos mediante new es más costosa en términos de tiempo o costo, el método clone puede obtener una mejora en términos de eficiencia.

Los lectores interesados en más contenido relacionado con Android pueden ver las secciones especiales de este sitio: 'Tutorial de Inicio y Avanzado de Desarrollo de Android', 'Técnicas de Depuración y Resolución de Problemas Comunes en Android', 'Resumen de Uso de Componentes Básicos de Android', 'Resumen de Técnicas de View de Android', 'Resumen de Técnicas de Layout de Android' y 'Resumen de Uso de Controles de Android'.

Espero que lo descrito en este artículo pueda ayudar a todos a diseñar programas Android.

Declaración: El contenido de este artículo se obtiene de la red, el derecho de autor pertenece al propietario original, el contenido se contribuye y carga de manera autónoma por los usuarios de Internet, este sitio web no posee los derechos de propiedad, no se ha procesado editorialmente por humanos y no asume responsabilidades legales relacionadas. Si encuentra contenido sospechoso de violación de derechos de autor, por favor envíe un correo electrónico a: notice#w proporcionando evidencia relevante, una vez que se verifique, este sitio eliminará inmediatamente el contenido sospechoso de violación de derechos de autor.3Declaración: El contenido de este artículo se obtiene de la red, el derecho de autor pertenece al propietario original, el contenido se contribuye y carga de manera autónoma por los usuarios de Internet, este sitio web no posee los derechos de propiedad, no se ha procesado editorialmente por humanos y no asume responsabilidades legales relacionadas. Si encuentra contenido sospechoso de violación de derechos de autor, por favor envíe un correo electrónico a: notice#w proporcionando evidencia relevante, una vez que se verifique, este sitio eliminará inmediatamente el contenido sospechoso de violación de derechos de autor.

Te gustará