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

Instance Explanation of Prototype Pattern in Android Programming Design Patterns

This article instance tells about the prototype pattern in Android programming design patterns. Share it with everyone for reference, as follows:

One, Introduction

The prototype pattern is a creational pattern. The word 'prototype' indicates that the model should have a sample instance, from which the user can copy an object with consistent internal properties, which is also known as 'cloning'. The copied instance is what we call the 'prototype', which is also customizable. The prototype model is often used to create complex or time-consuming instances, as copying an existing instance can make the program run more efficiently in this case.

Two, Definition

Specify the type of object to be created using the prototype instance and create new objects by copying these prototypes.

Three, Application Scenarios

(1When the class initialization consumes a lot of resources, including data, hardware resources, and so on, the prototype copy can avoid these consumptions.

(2When it is very cumbersome to produce an object through new, such as data preparation or access permission, the prototype pattern can be used.

(3When an object needs to be provided to other objects for access, and each caller may need to modify its value, it is advisable to use the prototype pattern to copy multiple objects for the caller to use, that is, protective copy.

It should be noted that the prototype pattern implemented through the Cloneable interface does not necessarily have a faster speed than that through the new operation when constructing instances by calling the clone function. Only when it takes a long time or high cost to construct objects through new can the clone method obtain an efficiency improvement. Therefore, when using Cloneable, it is necessary to consider the cost of constructing objects and do some efficiency tests. Of course, it is not necessary to implement the Cloneable interface to implement the prototype pattern, and there are also other implementation methods. Here, these will be explained one by one.

Four, UML Class Diagram of Prototype Model

Role introduction in the figure:

Client: The client user.

Prototype: An abstract class or interface that declares clone capability.

ConcretePrototype: The specific prototype class.

Five, Simple Implementation of Prototype Pattern

This section takes a simple document copy as an example to demonstrate the simple prototype pattern. In this example, we first create a document object, namely WordDocument, which contains text and images. After the user has spent a long time editing the content, they intend to make further edits to the document. However, it is not yet certain whether the edited document will be adopted, so for safety, the user needs to make a copy of the current document and then make modifications on the document copy. This is somewhat similar to the protective copy mentioned in the book 'Effective Java'. In this way, the original document is the prototype instance we mentioned above, which is the object to be 'cloned', and we call it the prototype:

Example code:

/**
 * Document type, acting as the ConcretePrototype role, while cloneable represents the prototype role.
 */
public class WordDocument implements Cloneable {
 //Text
 private String mText;
 //List of image names
 private ArrayList<String> mImages = new ArrayList<String>();
 public WordDocument(){
  System.out.println("-------- WordDocument constructor --------");
 }
 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);
 }
 /**
  * Print the document
  */
 public void showDocument(){
  System.out.println("-------- Word Content Start --------");
  System.out.println("Text : " + this.mText);
  System.out.println("Images List : ");
  for(String image : mImages){
   System.out.println("image name : " + image);
  }
  System.out.println("-------- Word Content End --------");
 }
 @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;
 }
}

Execution Method:

public static void main(String[] args) throws IOException {
  //1.Build a document object
  WordDocument originDoc = new WordDocument();
  //2.Edit the document, add images, etc.
  originDoc.setText("This is a document");
  originDoc.addImage("Image One");
  originDoc.addImage("Image Two");
  originDoc.addImage("Image three");
  originDoc.showDocument();
  //is copied as a prototype from the original document
  WordDocument doc2 = originDoc.clone();
  doc2.showDocument();
  //Modify the document copy
  doc2.setText("This is the modified Doc2text
  doc2.addImage("This is the newly added image");
  originDoc.showDocument();
  doc2.showDocument();
}

Execution result:

-------- WordDocument constructor --------
//originDoc
-------- Word Content Start --------
Text: This is a document
Images List:
image name: Image 1
image name: Image 2
image name: Image 3
-------- Word Content End --------
//doc2
-------- Word Content Start --------
Text: This is a document
Images List:
image name: Image 1
image name: Image 2
image name: Image 3
-------- Word Content End --------
//Modified copy after originDoc
-------- Word Content Start --------
Text: This is a document
Images List:
image name: Image 1
image name: Image 2
image name: Image 3
image name: This is the newly added image
-------- Word Content End --------
//Modified copy after doc2
-------- Word Content Start --------
Text: This is the modified Doc2Text
Images List:
image name: Image 1
image name: Image 2
image name: Image 3
image name: This is the newly added image
-------- Word Content End --------

Here we find that by modifying doc2After that, it only affected the mImages of originDoc without changing mText.

6. Shallow Copy and Deep Copy

actual implementation of the prototype pattern is just a shallow copy, also known as shadow copy. This copy does not actually reconstruct all fields of the original document, but the fields of the copy document reference the fields of the original document, as shown in the following figure:

careful readers may have noticed that the last two document information outputs are consistent. In the doc2has added an image, but it also appears in originDoc. What is going on? Those who have learned C++readers will have a profound understanding, because in the clone method of WordDocument mentioned above, only a shallow copy was performed, and the reference type new object doc2.mImages simply points to the this.mImages reference without reconstructing a new mImages object and adding the images from the original document to the new mImages object, which leads to the following problem with doc2.mImages refers to the same object as the original document, so if you modify the images in one document, the other document will also be affected. How can this problem be solved? The answer is to use deep copy, which means that when copying objects, the reference fields should also be copied rather than just referenced.

The clone method is modified as follows (other parts remain unchanged):

@Override
protected WordDocument clone(){
  try{
   WordDocument doc = (WordDocument)super.clone();
   doc.mText = this.mText;
   //Also call the clone() function on the mImages object for deep copy
   doc.mImages = (ArrayList<String>)this.mImages.clone();
   return doc;
  catch(Exception e){}
  return null;
}

The result of executing the above code after modification is:

-------- WordDocument constructor --------
//originDoc
-------- Word Content Start --------
Text: This is a document
Images List:
image name: Image 1
image name: Image 2
image name: Image 3
-------- Word Content End --------
//doc2
-------- Word Content Start --------
Text: This is a document
Images List:
image name: Image 1
image name: Image 2
image name: Image 3
-------- Word Content End --------
//Modified copy after originDoc
-------- Word Content Start --------
Text: This is a document
Images List:
image name: Image 1
image name: Image 2
image name: Image 3
-------- Word Content End --------
//Modified copy after doc2
-------- Word Content Start --------
Text: This is the modified Doc2Text
Images List:
image name: Image 1
image name: Image 2
image name: Image 3
image name: This is the newly added image
-------- Word Content End --------

It can be seen that they do not affect each other, which is called deep copy.

Following the above questions, in fact, the String type is the same as reference types in shallow copying, without a separate copy, but refers to the same address because String does not implement the cloneable interface, which means that only references can be copied. (We can check the source code to see this, while ArrayList implements the cloneable interface) But when modifying one of the values, a new block of memory is allocated to save the new value, and this reference points to the new memory space. Because the original String still has references pointing to it, it will not be recycled. So, although it is a copy of the reference, the value of the copied object is not changed when the value is modified.

Therefore, in many cases, we can treat the String in clone the same as primitive types, just pay attention to some details in the equals method.

The prototype pattern is a very simple pattern, the core problem of which is to copy the original object. One point to note when using this pattern is the issue of deep and shallow copying. During the development process, to reduce errors, the author suggests using deep copy as much as possible when using this pattern to avoid the problem of affecting the original object when operating the copy.

7. Prototype Pattern in Android Source Code

Example code:

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

8. Summary

The prototype pattern is essentially a copy of an object, similar to C++The copy constructor is somewhat similar, and the problems that are likely to occur between them are all related to deep and shallow copying. The prototype pattern can solve the problem of resource consumption in constructing complex objects and can improve the efficiency of object creation in some scenarios.

Advantages:

(1( The prototype pattern is a binary stream copy in memory, which is much better than directly creating a new object, especially when a large number of objects need to be generated within a loop, the prototype pattern may better reflect its advantages.)

(2( Another important use is protective copy, that is, an object may be read-only to the outside, in order to prevent external modification of this read-only object, it is usually possible to achieve the restriction of read-only by returning an object copy.)

Disadvantages:

(1( This is both its advantage and disadvantage, copying directly in memory, the constructor will not be executed. In actual development, attention should be paid to this potential problem. The advantage is to reduce constraints, and the disadvantage is also to reduce constraints, which needs to be considered in practical applications.)

(2(The prototype pattern implemented by the Cloneable interface does not necessarily have a faster speed than constructing an instance by calling the clone function, only when constructing an object through new operation is relatively time-consuming or costly, the clone method can obtain efficiency improvement.)

Readers who are interested in more content related to Android can check the special topics on this site: 'Android Development Tutorial for Beginners and Advanced Users', 'Summary of Android Debugging Techniques and Common Problem Solving Methods', 'Summary of Usage of Android Basic Components', 'Summary of Techniques of Android View View', 'Summary of Techniques of Android Layout Layout', and 'Summary of Usage of Android Controls'.

Hoping that the content described in this article will be helpful to everyone in Android program design.

Statement: The content of this article is from the Internet, the copyright belongs to the original author. The content is contributed and uploaded by Internet users spontaneously, and this website does not own the copyright. It has not been manually edited and does not assume any relevant legal liability. If you find any content suspected of copyright infringement, please send an email to: notice#oldtoolbag.com (Please replace # with @ when sending an email for reporting. Provide relevant evidence, and once verified, this site will immediately delete the content suspected of infringement.)

You May Also Like