English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Dieser Artikel beschreibt das Muster Prototypen im Android-Programmierungsdesign. Hiermit wird allen zur Verfügung gestellt und als Referenz verwendet, wie folgt:
I. Einführung
Das Prototypenmuster ist ein Mustertyp des Erzeugungstyps. Das Wort 'Prototyp' zeigt an, dass dieses Modell eine Mustervorlage haben sollte. Der Benutzer kopiert aus diesem Mustervorlagenobjekt ein Objekt mit identischen internen Attributen, der Prozess ist auch das, was wir als 'Klonen' bezeichnen. Das kopierte Beispiel ist das, was wir als 'Prototyp' bezeichnen, der ebenfalls anpassbar ist. Das Prototypenmuster wird häufig zur Erstellung komplexer oder zeitaufwendiger Instanzen verwendet, da in diesem Fall die Kopie eines bestehenden Beispiels die Programmausführung effizienter macht.
II. Definition
Durch die Verwendung eines Prototypenbeispiels wird die Art der zu erstellenden Objekte angegeben, und neue Objekte werden durch Kopieren dieser Prototypen erstellt.
III. Anwendungsszenario
(1)Die Initialisierung der Klasse erfordert sehr viele Ressourcen, darunter Daten und Hardwareressourcen. Durch die Prototypenkopie können diese Verbrauchungen vermieden werden.
(2)Das Erstellen eines Objekts durch new erfordert sehr aufwendige Datenvorparation oder Zugriffsrechte, in diesem Fall kann das Prototypenmuster verwendet werden.
(3)Ein Objekt muss von anderen Objekten aufgerufen werden und jeder Aufrufer möglicherweise seinen Wert ändern, in diesem Fall kann das Prototypenmuster verwendet werden, um mehrere Kopien des Objekts für die Aufrufer bereitzustellen, d.h. schützende Kopie.
Zu beachten ist, dass das Prototypenmuster, das durch das Implementieren des Cloneable-Interfaces durchgeführt wird, beim Konstruieren von Instanzen durch Aufruf der clone-Funktion nicht unbedingt schneller ist als durch das new-Operator. Nur wenn das Konstruieren von Objekten durch new zeitaufwendig oder kostspielig ist, kann durch den clone-Methoden eine Effizienzsteigerung erreicht werden. Daher muss bei der Verwendung von Cloneable über die Kosten der Objektkonstruktion und einige Effizienztests nachgedacht werden. Natürlich muss das Prototypenmuster nicht unbedingt durch das Implementieren des Cloneable-Interfaces realisiert werden. Es gibt auch andere Implementierungsmöglichkeiten, die hier nacheinander erläutert werden.
IV. UML-Klassendiagramm des Prototypenmodells
Figurenbeschreibung im Diagramm:
Client: Clientbenutzer.
Prototype: Abstrakte Klasse oder Interface, das die Fähigkeit zum Clone erklären.
ConcretePrototype: Konkrete Prototypenklasse.
V. Einfache Implementierung des Prototypenmusters
Hier wird ein einfaches Dokumentkopieren als Beispiel für das einfache Prototypenmuster gezeigt. In diesem Beispiel wird zunächst ein Dokumentobjekt, das WordDocument genannt wird, erstellt, das Text und Bilder enthält. Nach einer langen Inhaltserstellung plant der Benutzer, das Dokument weiter zu bearbeiten. Ob der geänderte Dokument jedoch übernommen wird, ist noch unklar. Daher muss der Benutzer aus Sicherheitsgründen eine Kopie des aktuellen Dokuments erstellen und diese Kopie bearbeiten. Dies ähnelt dem Schutzkopieren im Buch 'Effective Java'. So ist das ursprüngliche Dokument unser oben erwähntes Musterbeispiel, das als zu 'klonen'es Objekt bezeichnet wird, das wir als Prototyp bezeichnen:
Beispielcode:
/** * Dokumenttyp, der die Rolle des ConcretePrototype spielt, während cloneable die Rolle des Prototype darstellt. */ public class WordDocument implements Cloneable { //Text private String mText; //图片名列表 private ArrayList<String> mImages = new ArrayList<String>(); public WordDocument(){ System.out.println("-------- Konstruktor der 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("-------- 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; } }
执行方法:
public static void main(String[] args) throws IOException { //1.构建文档对象 WordDocument originDoc = new WordDocument(); //2.编辑文档,添加图片等 originDoc.setText("这是一篇文档"); originDoc.addImage("图片一"); originDoc.addImage("图片二"); originDoc.addImage("Image three"); originDoc.showDocument(); //to copy a copy based on 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:
-------- Konstruktor der WordDocument -------- //originDoc -------- Word Content Start -------- Text: Dies ist ein Dokument Bilderliste: Bilddateiname: Bild eins Bilddateiname: Bild zwei Bilddateiname: Bild drei -------- Word Content End -------- //doc2 -------- Word Content Start -------- Text: Dies ist ein Dokument Bilderliste: Bilddateiname: Bild eins Bilddateiname: Bild zwei Bilddateiname: Bild drei -------- Word Content End -------- //Nach der Änderung der Kopie originDoc -------- Word Content Start -------- Text: Dies ist ein Dokument Bilderliste: Bilddateiname: Bild eins Bilddateiname: Bild zwei Bilddateiname: Bild drei Bilddateiname: Dies ist das hinzugefügte Bild -------- Word Content End -------- //Nach der Änderung der Kopie doc2 -------- Word Content Start -------- Text: Dies ist das geänderte Doc2Text Bilderliste: Bilddateiname: Bild eins Bilddateiname: Bild zwei Bilddateiname: Bild drei Bilddateiname: Dies ist das hinzugefügte Bild -------- Word Content End --------
Here we find that by modifying doc2After that, it only affected the mImages of originDoc, without changing mText.
Six, shallow copy and deep copy
the implementation of the above prototype pattern is actually 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 refer to the fields of the original document, as shown in the following figure:
may notice from the above results that the information output of the last two documents is consistent. In doc2has added an image, but it also appears in originDoc, what is the matter? Readers 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 and does not construct a new mImages object, and then add the images in the original document to the new mImages object, which leads to doc2.mImages refers to the same object as the original document, so if you modify an image in one document, the other document will also be affected. So how do we solve this problem? The answer is to use deep copy, which means that when copying an object, the fields of reference type should also be copied in the form of copying, not simply referred to.
The clone method is modified as follows (other 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; }
After modification, the result of executing the above code is:
-------- Konstruktor der WordDocument -------- //originDoc -------- Word Content Start -------- Text: Dies ist ein Dokument Bilderliste: Bilddateiname: Bild eins Bilddateiname: Bild zwei Bilddateiname: Bild drei -------- Word Content End -------- //doc2 -------- Word Content Start -------- Text: Dies ist ein Dokument Bilderliste: Bilddateiname: Bild eins Bilddateiname: Bild zwei Bilddateiname: Bild drei -------- Word Content End -------- //Nach der Änderung der Kopie originDoc -------- Word Content Start -------- Text: Dies ist ein Dokument Bilderliste: Bilddateiname: Bild eins Bilddateiname: Bild zwei Bilddateiname: Bild drei -------- Word Content End -------- //Nach der Änderung der Kopie doc2 -------- Word Content Start -------- Text: Dies ist das geänderte Doc2Text Bilderliste: Bilddateiname: Bild eins Bilddateiname: Bild zwei Bilddateiname: Bild drei Bilddateiname: Dies ist das hinzugefügte Bild -------- Word Content End --------
Es ist erkennbar, dass sie sich nicht gegenseitig beeinflussen, was tiefes Kopieren genannt wird.
Weiterführend zur obigen Frage, der String-Typ ist bei flachem Kopieren wie Referenztypen, es wird keine separate Kopie erstellt, sondern auf denselben Adressraum verwiesen. Da String das Interface cloneable nicht implementiert, kann nur eine Referenz kopiert werden. (Wir können dies im Quellcode überprüfen, während ArrayList das Interface cloneable implementiert). Wenn jedoch einer der Werte geändert wird, wird ein neues Speicherbereich neu zugeordnet, um den neuen Wert zu speichern, und die Referenz weist auf diesen neuen Speicherbereich hin. Da der ursprüngliche String noch eine Referenz darauf hat, wird er nicht recycelt. Daher wird, obwohl es sich um eine Referenzkopie handelt, der Wert des kopierten Objekts beim Ändern des Wertes nicht geändert.
Daher können wir in vielen Fällen String bei der Klonung so behandeln wie Basistypen, wir müssen nur bei der equals-Operation einige Punkte beachten.
Das Prototypenmuster ist sehr einfach, und das Kernproblem ist die Kopie des Originalobjekts. Ein zu beachtendes Punkt im Verlauf der Verwendung dieses Musters ist: das Problem des tiefen und flachen Kopierens. Während der Entwicklung, um Fehler zu reduzieren, empfiehlt der Autor, bei der Verwendung dieses Musters so weit wie möglich tiefes Kopieren zu verwenden, um das Problem zu vermeiden, dass die Kopie des Originalobjekts beeinflusst wird.
Sieben, das Prototypenmuster im Android-Quellcode
Beispielcode:
Uri uri = Uri.parse("smsto:");110"); Intent intent = new Intent(Intent.ACTION_SEND,uri); intent.putExtra("sms_body", "The SMS text"); //Klonen Intent intent2 = (Intent)intent.clone(); startActivity(intent2);
Achtung, Zusammenfassung
Das Prototypenmuster ist im Wesentlichen eine Kopie des Objekts, und im Vergleich zu C++Die Kopierkonstruktor sind ähnlich, und die Probleme, die zwischen ihnen auftreten können, sind tiefes und flaches Kopieren. Das Prototypenmuster kann das Problem der Ressourcenverbrauch beim Aufbau komplexer Objekte lösen und die Effizienz der Objekterstellung in einigen Szenarien verbessern.
优点:
(1)原型模式是在内存中二进制流的拷贝,要比直接new一个对象性能好很多,特别是要在一个循环体内产生大量对象时,原型模式可能更好的体现其优点。
(2)还有一个重要的用途就是保护性拷贝,也就是对某个对象对外可能是只读的,为了防止外部对这个只读对象的修改,通常可以通过返回一个对象拷贝的形式实现只读的限制。
缺点:
(1)这既是它的优点也是缺点,直接在内存中拷贝,构造函数是不会执行的,在实际开发中应该注意这个潜在问题。优点是减少了约束,缺点也是减少了约束,需要大家在实际应用时考虑。
(2)通过实现Cloneable接口的原型模式在调用clone函数构造实例时并不一定比通过new操作速度快,只有当通过new构造对象较为耗时或者说成本较高时,通过clone方法才能够获得效率上的提升。
更多关于Android相关内容感兴趣的读者可查看本站专题:《Android开发入门与进阶教程》、《Android调试技巧与常见问题解决方法汇总》、《Android基本组件用法总结》、《Android视图View技巧总结》、《Android布局layout技巧总结》及《Android控件用法总结》
希望本文所述对大家的Android程序设计有所帮助。
声明:本文内容来源于网络,版权归原作者所有。内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:notice#oldtoolbag.com(在发送邮件时,请将#更换为@进行举报,并提供相关证据。一经查实,本站将立即删除涉嫌侵权内容。)