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

Explicação detalhada do padrão de design de origem Android com exemplo

Este artigo descreve o padrão de protótipo no design de programação Android. Compartilho com vocês para referência, conforme a seguir:

Um, Introdução

O padrão de protótipo é um padrão de criação. As duas palavras 'protótipo' indicam que o modelo deve ter um exemplo padrão, o usuário copia um objeto interno idêntico a partir deste objeto padrão, este processo é conhecido como 'clonagem' em nosso vocabulário. O exemplo copiado é o que chamamos de 'protótipo', que também é personalizável. O modelo de protótipo é frequentemente usado para criar instâncias complexas ou de construção demorada, porque, neste caso, copiar uma instância existente pode tornar o programa mais eficiente.

Dois, Definição

Usar o exemplo de protótipo para especificar o tipo de objeto a ser criado e criar novos objetos copiando esses protótipos.

Três, Cenários de uso

(1A inicialização da classe requer muitos recursos, incluindo dados e recursos de hardware, evitando esses custos através da cópia de protótipo.

(2A criação de um objeto através de new requer preparação de dados complexa ou permissão de acesso, neste caso, pode-se usar o padrão de protótipo.

(3Um objeto precisa fornecer acesso a outros objetos e, possivelmente, cada chamador precisa modificar seu valor, neste caso, pode-se considerar usar o padrão de protótipo para copiar vários objetos para uso pelos chamadores, ou seja, cópia protetiva.

É necessário notar que, ao usar o padrão de protótipo que implementa a interface Cloneable, não é necessariamente mais rápido que usar a operação new ao chamar a função clone para construir uma instância, apenas quando a construção de um objeto através de new é demorada ou custosa, então o método clone pode obter uma melhoria de eficiência. Portanto, ao usar Cloneable, é necessário considerar o custo de construção do objeto e fazer alguns testes de eficiência. Claro, a implementação do padrão de protótipo não precisa necessariamente implementar a interface Cloneable, também há outras maneiras de implementar, aqui será explicado um por um.

Quatro, Diagrama de classes UML do modelo de protótipo

Introdução dos personagens na figura:

Client: usuário do cliente.

Prototype: classe abstrata ou interface, que declara a capacidade de clone.

ConcretePrototype: classe de protótipo específica.

Cinco, Implementação simples do padrão de protótipo

Aqui está um exemplo simples de cópia de documento para demonstrar o padrão de protótipo. Neste exemplo, primeiro criamos um objeto de documento, ou WordDocument, que contém texto e imagens. Após uma longa edição de conteúdo, o usuário deseja fazer mais edições no documento, mas não é certo se este documento editado será adotado, então, para segurança, o usuário precisa fazer uma cópia do documento atual e, em seguida, modificar a cópia do documento. Isso é semelhante ao que é mencionado em 'Effective Java', chamado de cópia protetiva. Assim, o documento original é o exemplo mencionado acima, ou seja, o exemplo padrão mencionado acima, que será 'clonado', chamamos de protótipo:

Exemplo 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("-------- construtor 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("-------- Início do conteúdo do 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("-------- Fim do conteúdo do 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 é a nova imagem adicionada");
  //originDoc.addImage("Imagem três");
  fazendo uma cópia de um protótipo do documento original2 WordDocument doc
  doc2originDoc.showDocument();
  //= originDoc.clone();
  doc2modificação da cópia do documento2.setText("Este é o Doc
  doc2texto");
  .addImage("Esta é a nova imagem adicionada");
  doc2originDoc.showDocument();
}

.showDocument();

-------- construtor WordDocument --------
//originDoc
-------- Início do conteúdo do Word --------
Texto: Este é um documento
Lista de imagens:
nome da imagem: Imagem um
nome da imagem: Imagem dois
nome da imagem: Imagem três
-------- Fim do conteúdo do Word --------
//doc2
-------- Início do conteúdo do Word --------
Texto: Este é um documento
Lista de imagens:
nome da imagem: Imagem um
nome da imagem: Imagem dois
nome da imagem: Imagem três
-------- Fim do conteúdo do Word --------
//modificação de cópia após a revisão originDoc
-------- Início do conteúdo do Word --------
Texto: Este é um documento
Lista de imagens:
nome da imagem: Imagem um
nome da imagem: Imagem dois
nome da imagem: Imagem três
nome da imagem: Esta é a imagem adicionada recentemente
-------- Fim do conteúdo do Word --------
//modificação de cópia após a revisão doc2
-------- Início do conteúdo do Word --------
Texto: Este é o Doc modificado2Texto
Lista de imagens:
nome da imagem: Imagem um
nome da imagem: Imagem dois
nome da imagem: Imagem três
nome da imagem: Esta é a imagem adicionada recentemente
-------- Fim do conteúdo do Word --------

O resultado da execução:2Aqui, observamos que, ao modificar o doc

Depois disso, apenas afetou o mImages do originDoc, sem alterar o mText.

Seis, cópia superficial e cópia profunda

a implementação do padrão de protótipo acima é realmente uma cópia superficial, também conhecida como cópia de sombra, essa cópia não reconstitui todos os campos do documento original, mas os campos do documento secundário referenciam os campos do documento original, como na figura a seguir:2um novo arquivo de imagem, mas também apareceu no originDoc, o que acontece? Os leitores atentos podem notar que as informações dos últimos dois documentos são idênticas. Nós no doc++os leitores terão uma experiência muito profunda, pois no método clone do WordDocument mencionado anteriormente foi feita apenas uma cópia superficial, o novo objeto doc2.mImages apenas aponta para a referência this.mImages, sem reconstruir um novo objeto mImages, adicionando as imagens do documento original ao novo objeto mImages, o que leva a doc2.mImages e o objeto do documento original são o mesmo, portanto, se modificarmos a imagem de um documento, o outro também será afetado. Então, como resolver esse problema? A resposta é usar a cópia profunda, ou seja, ao copiar o objeto, também usar a cópia para os campos de tipo de referência, em vez de simplesmente referências.

A modificação do método clone é conforme abaixo (outros não alterados):

@Override
protected WordDocument clone(){
  try{
   WordDocument doc = (WordDocument)super.clone();
   doc.mText = this.mText;
   //Também chamamos a função clone() no objeto mImages, realizando uma cópia profunda.
   doc.mImages = (ArrayList<String>)this.mImages.clone();
   return doc;
  catch(Exception e){}
  return null;
}

O resultado da execução do código acima após a modificação é:

-------- construtor WordDocument --------
//originDoc
-------- Início do conteúdo do Word --------
Texto: Este é um documento
Lista de imagens:
nome da imagem: Imagem um
nome da imagem: Imagem dois
nome da imagem: Imagem três
-------- Fim do conteúdo do Word --------
//doc2
-------- Início do conteúdo do Word --------
Texto: Este é um documento
Lista de imagens:
nome da imagem: Imagem um
nome da imagem: Imagem dois
nome da imagem: Imagem três
-------- Fim do conteúdo do Word --------
//modificação de cópia após a revisão originDoc
-------- Início do conteúdo do Word --------
Texto: Este é um documento
Lista de imagens:
nome da imagem: Imagem um
nome da imagem: Imagem dois
nome da imagem: Imagem três
-------- Fim do conteúdo do Word --------
//modificação de cópia após a revisão doc2
-------- Início do conteúdo do Word --------
Texto: Este é o Doc modificado2Texto
Lista de imagens:
nome da imagem: Imagem um
nome da imagem: Imagem dois
nome da imagem: Imagem três
nome da imagem: Esta é a imagem adicionada recentemente
-------- Fim do conteúdo do Word --------

Pode ser visto que eles não se influenciam mutuamente, isso é chamado de cópia profunda.

Continuando a duvida acima, o tipo String, na cópia superficial, é semelhante aos tipos de referência, não há cópia separada, mas referencia o mesmo endereço, porque a String não implementou o interface cloneable, o que significa que só pode copiar a referência. (Podemos verificar o código-fonte para ver que ArrayList implementou o interface cloneable) Mas quando alteramos um dos valores, uma nova memória é alocada para armazenar o novo valor, e a referência aponta para o novo espaço de memória. A String original, porque ainda há referências apontando para ela, não será recolhida. Portanto, embora seja uma cópia de referência, a alteração do valor não altera o valor do objeto copiado.

Portanto, em muitos casos, podemos tratar a String da mesma forma que os tipos básicos durante a clonagem, apenas precisamos prestar atenção a alguns detalhes no equals.

O padrão de protótipo é muito simples, o problema central é a cópia do objeto original. Uma coisa a ser notada no uso deste padrão é o problema de cópia profunda e superficial. Durante o desenvolvimento, para reduzir os erros, o autor recomenda usar a cópia profunda o mais possível ao usar este padrão, evitando problemas de impacto no objeto original ao operar a cópia.

Sétimo, o padrão de protótipo no código-fonte do Android

Exemplo de código:

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

Oitavo, resumo

O padrão de protótipo essencialmente é uma cópia de objetos, e é semelhante ao C++A função de cópia construtora no meio é um pouco semelhante, os problemas que eles podem ter são todos cópia profunda e cópia superficial. O padrão de protótipo pode resolver o problema de consumo de recursos na construção de objetos complexos e pode melhorar a eficiência da criação de objetos em alguns cenários.

Vantagem:

(1(O padrão Prototype é uma cópia binária na memória, o que é muito melhor do que criar um objeto diretamente via new, especialmente quando é necessário criar muitos objetos dentro de um loop. O padrão Prototype pode melhor mostrar seus pontos fortes nessa situação.)

(2(Outra importante função é a cópia protetiva, ou seja, para um objeto que pode ser apenas leitura externamente, para evitar que o objeto de leitura apenas seja modificado externamente, geralmente é possível implementar a restrição de leitura apenas retornando uma cópia do objeto.)

Desvantagem:

(1(Isso é tanto uma vantagem quanto uma desvantagem, copiando diretamente na memória, o construtor não é executado. Na prática, deve-se prestar atenção a esse problema potencial. A vantagem é a redução das restrições, e a desvantagem também é a redução das restrições, o que deve ser considerado na aplicação prática.)

(2(A implementação do padrão Prototype no método clone não é necessariamente mais rápida do que a criação de instâncias via new, especialmente quando a criação de objetos via new é demorada ou cara. A eficiência pode ser melhorada apenas quando a criação de objetos via new é demorada ou cara.)

Leitores interessados em mais conteúdo sobre Android podem consultar as seções especiais do site: 'Introdução e Aperfeiçoamento em Desenvolvimento Android', 'Dicas de Depuração e Solução de Problemas Comuns em Android', 'Resumo de Uso dos Componentes Básicos em Android', 'Resumo de Técnicas de View em Android', 'Resumo de Técnicas de Layout em Android' e 'Resumo de Uso dos Controles em Android'.

Espero que o conteúdo deste artigo ajude a todos na programação de aplicativos Android.

Declaração: O conteúdo deste artigo é de origem na internet, pertencente ao respectivo autor. O conteúdo é contribuído e carregado voluntariamente pelos usuários da internet. Este site não possui direitos autorais, não foi editado manualmente e não assume responsabilidade legal. Se você encontrar conteúdo suspeito de violação de direitos autorais, por favor, envie um e-mail para: notice#oldtoolbag.com (ao enviar e-mail, substitua # por @ para denunciar e forneça provas relevantes. Caso seja confirmado, o site deletará imediatamente o conteúdo suspeito de violação de direitos autorais.)

Você também pode gostar