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

Esempio dettagliato del modello di design dell'Android Prototype

Questo articolo illustra un esempio di modello di progettazione di programmazione Android: modello di prototipo. Condividiamo con tutti per riferimento, come segue:

Yi, presentazione

Il modello di prototipo è un modello di creazione. Le parole 'prototipo' indicano che il modello dovrebbe avere un'istanza di modello, dall'oggetto modello, copiare un oggetto con attributi interni identici, questo processo è anche noto come 'clonazione'. L'istanza copiata è ciò che chiamiamo 'prototipo', e questo prototipo è personalizzabile. Il modello di prototipo viene utilizzato spesso per creare istanze complesse o costose da costruire, perché in questo caso, copiare un'istanza esistente può rendere il programma più efficiente.

Dui, definizione

Utilizzare un'istanza di prototipo per specificare il tipo di oggetto da creare e creare nuovi oggetti copiando questi prototipi.

Tre, scenari d'uso

(1) L'inizializzazione della classe richiede molte risorse, inclusi dati e risorse hardware, e attraverso la copia del prototipo si evitano queste consumazioni.

(2) Quando la creazione di un oggetto attraverso new richiede dati di preparazione o permessi di accesso molto complessi, si può utilizzare il modello di prototipo.

(3) Quando un oggetto deve essere fornito ad altri oggetti per l'accesso e diversi chiamanti potrebbero dover modificare il suo valore, si può considerare di utilizzare il modello di prototipo per copiare più oggetti per l'uso dei chiamanti, ovvero copia protettiva.

È necessario notare che, quando si chiama la funzione clone per costruire un'istanza attraverso l'implementazione dell'interfaccia Cloneable, non è necessariamente più veloce rispetto all'operazione new. Solo quando la creazione di un oggetto attraverso new è costosa in termini di tempo o di costo, l'uso del metodo clone può ottenere un miglioramento dell'efficienza. Pertanto, quando si utilizza Cloneable, è necessario considerare il costo della costruzione dell'oggetto e fare alcuni test di efficienza. Naturalmente, l'implementazione del modello di prototipo non deve necessariamente implementare l'interfaccia Cloneable, ci sono anche altri modi di implementazione, che saranno spiegati uno per uno.

Quattro, diagramma UML della classe del modello di prototipo

Introduzione dei ruoli nella figura:

Client: utente del client.

Prototype: classe astratta o interfaccia, che dichiara di avere capacità di clonazione.

ConcretePrototype: classe di prototipo specifica.

Cinque, implementazione semplice del modello di prototipo

Di seguito, con un esempio semplice di copia di documento, mostriamo un esempio semplice del modello di prototipo. In questo esempio, prima di tutto, creiamo un oggetto documento, ovvero WordDocument, che contiene testo e immagini. Dopo aver editato il contenuto per un lungo periodo, l'utente intende fare ulteriori modifiche al documento, ma non è ancora chiaro se questo documento modificato sarà adottato. Pertanto, per motivi di sicurezza, l'utente deve fare una copia del documento corrente e poi modificare la copia del documento. Questo è simile alla copia protettiva menzionata nel libro "Effective Java". In questo modo, il documento originale è quello che chiamiamo esempio di istanza campione, ovvero l'oggetto che verrà "clonato", e noi lo chiamiamo prototipo:

Esempio di codice:

*/
 * Tipo di documento, che gioca il ruolo di ConcretePrototype, mentre cloneable rappresenta il ruolo di prototype
 */
public class WordDocument implements Cloneable {
 //Testo
 private String mText;
 //Elenco dei nomi delle immagini
 private ArrayList<String> mImages = new ArrayList<String>();
 public WordDocument(){
  System.out.println("-------- WordDocument costruttore --------");
 }
 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);
 }
 */
  /* Stampa documento
  */
 public void showDocument(){
  System.out.println("-------- Inizio del Contenuto del Word --------");
  System.out.println("Testo : " + this.mText);
  System.out.println("Elenco Immagini : ");
  for(String image : mImages){
   System.out.println("Nome immagine : " + image);
  }
  System.out.println("-------- Fine del Contenuto del 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;
 }
}

Esegui metodo:

public static void main(String[] args) throws IOException {
  //1. Costruzione dell'oggetto documento
  WordDocument originDoc = new WordDocument();
  //2. Modifica del documento, aggiunta di immagini ecc.
  originDoc.setText("Questo è un documento");
  originDoc.addImage("Immagine uno");
  originDoc.addImage("Immagine due");
  originDoc.addImage("Immagine tre");
  originDoc.showDocument();
  //Copia di un documento originale
  WordDocument doc2 = originDoc.clone();
  doc2.showDocument();
  //Modifica del documento duplicato
  doc2.setText("Questo è il testo modificato di Doc2");
  doc2.addImage("Questa è l'immagine aggiunta di recente");
  originDoc.showDocument();
  doc2.showDocument();
}

Risultato dell'esecuzione:

-------- Costruttore WordDocument --------
//originDoc
-------- Inizio del Contenuto Word --------
Testo: Questo è un documento
Elenco delle immagini:
nome immagine: Immagine uno
nome immagine: Immagine due
nome immagine: Immagine tre
-------- Fine del Contenuto Word --------
//doc2
-------- Inizio del Contenuto Word --------
Testo: Questo è un documento
Elenco delle immagini:
nome immagine: Immagine uno
nome immagine: Immagine due
nome immagine: Immagine tre
-------- Fine del Contenuto Word --------
//Modifica del duplicato dopo originDoc
-------- Inizio del Contenuto Word --------
Testo: Questo è un documento
Elenco delle immagini:
nome immagine: Immagine uno
nome immagine: Immagine due
nome immagine: Immagine tre
nome immagine: Questo è l'immagine aggiunta di recente
-------- Fine del Contenuto Word --------
//Modifica del duplicato dopo doc2
-------- Inizio del Contenuto Word --------
Testo: Questo è il testo Doc2 modificato
Elenco delle immagini:
nome immagine: Immagine uno
nome immagine: Immagine due
nome immagine: Immagine tre
nome immagine: Questo è l'immagine aggiunta di recente
-------- Fine del Contenuto Word --------

Notiamo che dopo aver modificato doc2, ha influenzato solo mImages di originDoc, ma non ha cambiato mText.

Sezione 6: Copia superficiale e copia profonda

L'implementazione dell'原型 modello menzionata sopra è in realtà una copia superficiale, anche nota come copia ombra. Questa copia non ricostruisce tutti i campi del documento originale, ma i campi del documento derivato si riferiscono ai campi del documento originale, come illustrato nella seguente figura:

Un lettore attento potrebbe notare che le ultime due informazioni sui documenti sono identiche. Abbiamo aggiunto un'immagine a doc2, ma essa è stata visualizzata anche in originDoc, cos'è successo? Chi ha studiato C++ avrà una comprensione più profonda di questo problema. Questo è dovuto al fatto che il metodo clone di WordDocument menzionato sopra ha eseguito solo una copia superficiale. L'oggetto di tipo ArrayList<String> doc2.mImages si riferisce semplicemente all'oggetto this.mImages, senza costruire un nuovo oggetto mImages e aggiungere le immagini del documento originale a questo nuovo oggetto mImages. Di conseguenza, doc2.mImages e l'oggetto del documento originale sono lo stesso oggetto. Pertanto, la modifica di una delle immagini nel documento influisce anche sull'altro documento. Allora come possiamo risolvere questo problema? La risposta è utilizzare una copia profonda, ossia copiare anche i campi di tipo riferimento durante la copia dell'oggetto.

La modifica del metodo clone è la seguente (il resto rimane invariato):

@Override
protected WordDocument clone(){
  try{
   WordDocument doc = (WordDocument)super.clone();
   doc.mText = this.mText;
   //Anche per l'oggetto mImages viene chiamata la funzione clone() per effettuare una copia profonda
   doc.mImages = (ArrayList<String>)this.mImages.clone();
   return doc;
  }catch(Exception e){}
  return null;
}

Modificato, l'esito dell'esecuzione del codice sopra è:

-------- Costruttore WordDocument --------
//originDoc
-------- Inizio del Contenuto Word --------
Testo: Questo è un documento
Elenco delle immagini:
nome immagine: Immagine uno
nome immagine: Immagine due
nome immagine: Immagine tre
-------- Fine del Contenuto Word --------
//doc2
-------- Inizio del Contenuto Word --------
Testo: Questo è un documento
Elenco delle immagini:
nome immagine: Immagine uno
nome immagine: Immagine due
nome immagine: Immagine tre
-------- Fine del Contenuto Word --------
//Modifica del duplicato dopo originDoc
-------- Inizio del Contenuto Word --------
Testo: Questo è un documento
Elenco delle immagini:
nome immagine: Immagine uno
nome immagine: Immagine due
nome immagine: Immagine tre
-------- Fine del Contenuto Word --------
//Modifica del duplicato dopo doc2
-------- Inizio del Contenuto Word --------
Testo: Questo è il testo Doc2 modificato
Elenco delle immagini:
nome immagine: Immagine uno
nome immagine: Immagine due
nome immagine: Immagine tre
nome immagine: Questo è l'immagine aggiunta di recente
-------- Fine del Contenuto Word --------

Si può vedere che non influenzano l'uno l'altro, questo si chiama copia profonda.

Proseguendo con la domanda precedente, in effetti, il tipo String è uguale al tipo di riferimento durante la copia superficiale, non c'è una copia separata, ma c'è un riferimento allo stesso indirizzo, perché String non ha implementato l'interfaccia cloneable, il che significa che può copiare solo i riferimenti. (Possiamo vedere il codice sorgente per questo, mentre ArrayList ha implementato l'interfaccia cloneable). Ma quando si modifica uno dei valori, si assegna una nuova area di memoria per conservare il nuovo valore, e il riferimento punta a questa nuova area di memoria. Poiché l'originale String esiste ancora e ha un riferimento verso di esso, non viene raccolto. Quindi, anche se si copia il riferimento, non si cambia il valore dell'oggetto copiato.

Quindi, in molti casi, possiamo trattare String come tipi di base durante la copia, ma dobbiamo solo notare alcune cose durante l'uso di equals.

Il modello prototipo è molto semplice, il suo problema centrale è la copia dell'oggetto originale. Un punto da notare durante l'uso di questo modello è il problema della copia profonda e superficiale. Durante lo sviluppo, per ridurre gli errori, l'autore consiglia di utilizzare il modello prototipo preferibilmente con la copia profonda per evitare problemi di influenzare l'oggetto originale durante l'operazione sui duplicati.

Sette, Il modello prototipo nel codice sorgente di Android

Esempio di codice:

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

Otto, Sommario

Il modello prototipo è essenzialmente una copia di oggetti, simile al costruttore di copia in C++, e i problemi che possono sorgere tra loro riguardano principalmente la copia profonda e superficiale. L'uso del modello prototipo può risolvere il problema della consumo di risorse nella costruzione di oggetti complessi e può migliorare l'efficienza nella creazione di oggetti in alcune situazioni.

Vantaggio:

(1) Il pattern Prototype è una copia binaria in memoria, è molto migliore rispetto alla creazione diretta di un oggetto tramite new, specialmente quando è necessario generare molti oggetti all'interno di un ciclo, il pattern Prototype può meglio manifestare i suoi vantaggi.

(2) Un altro uso importante è la copia protettiva, ossia per un oggetto che potrebbe essere solo leggibile dall'esterno, per prevenire la modifica dell'oggetto solo leggibile dall'esterno, di solito è possibile implementare il limite di sola lettura restituendo una copia dell'oggetto.

Svantaggio:

(1) Questo è sia un vantaggio che un svantaggio, la copia diretta in memoria non esegue il costruttore, in sviluppo reale deve essere prestata attenzione a questo problema potenziale. Il vantaggio è la riduzione delle restrizioni, il svantaggio è anche la riduzione delle restrizioni, è necessario considerare questi aspetti在实际应用时.

(2) Implementare il pattern Prototype attraverso l'interfaccia Cloneable non garantisce necessariamente una velocità superiore rispetto alla creazione di un'istanza tramite new, solo quando la creazione di un oggetto tramite new è particolarmente lenta o costosa, l'uso del metodo clone può ottenere un miglioramento dell'efficienza.

Leggi di più sui contenuti relativi a Android interessanti nel nostro argomento: 'Guida all'inizio e all'avanzamento dello sviluppo Android', 'Tecniche di debug e soluzioni comuni ai problemi di Android', 'Sommarizzazione dell'uso dei componenti base di Android', 'Sommarizzazione delle tecniche di View di Android', 'Sommarizzazione delle tecniche di layout di Android' e 'Sommarizzazione dell'uso dei controlli di Android'.

Spero che l'articolo sia utile per la progettazione di applicazioni Android.

Dichiarazione: il contenuto di questo articolo è stato tratto da Internet, il copyright è dell'autore originale, il contenuto è stato contribuito e caricato autonomamente dagli utenti di Internet, questo sito non possiede il diritto di proprietà, non è stato editato manualmente e non assume responsabilità legali correlate. Se trovi contenuti sospetti di violazione del copyright, ti preghiamo di inviare una email a: notice#oldtoolbag.com (al momento dell'invio dell'email, sostituisci # con @) per segnalare, fornendo prove pertinenti. Una volta verificata, questo sito cancellerà immediatamente il contenuto sospetto di violazione del copyright.

Ti potrebbe interessare