[关闭]
@Beeder 2017-08-21T16:30:17.000000Z 字数 3269 阅读 820

Android源码设计模式 学习笔记(四) 原型模式

android



第四章 原型模式

4.1 定义

    用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。被复制的实例就是“原型”,这个原型是可定制的。

注意:clone是Object中的方法

4.2 使用场景

4.3 角色介绍

贴图库
角色介绍如下:
* Client:客户端用户。
* Prototype:抽象类或者接口、声明具备clone能力。
* ConcretePrototype:具体的实现类。

4.4 简单实现

浅拷贝

  1. //Book类扮演的是ConcretePrototype角色,Cloneable类扮演的是Prototype角色
  2. public class Book implements Cloneable{
  3. private String title;
  4. private ArrayList<String> image = new ArrayList<String>();
  5. public Book() {
  6. super();
  7. }
  8. public Book(String title) {
  9. super();
  10. this.title = title;
  11. }
  12. public ArrayList<String> getImage(){
  13. return image;
  14. }
  15. public void addImage(String img){
  16. this.image.add(img);
  17. }
  18. public String getTitle() {
  19. return title;
  20. }
  21. public void setTitle(String title) {
  22. this.title = title;
  23. }
  24. @Override
  25. protected Object clone() throws CloneNotSupportedException {
  26. Book book = (Book)super.clone();
  27. book.title = this.title;
  28. book.image = this.image;
  29. return book;
  30. }
  31. public void showBook(){
  32. System.out.println("=====Start=====");
  33. System.out.println("title:"+title);
  34. for(String img : image){
  35. System.out.println("image name:"+img);
  36. }
  37. System.out.println("======End======");
  38. }
  39. }

执行main方法:

  1. public static void main(String[] args) {
  2. try {
  3. Book book1 = new Book("书1");
  4. book1.addImage("图1");
  5. //第1次输出
  6. book1.showBook();
  7. Book book2 = (Book) book1.clone();
  8. //第2次输出
  9. book2.showBook();
  10. book2.setTitle("书2");
  11. book2.addImage("图2");
  12. //第3次输出
  13. book2.showBook();
  14. //第4次输出
  15. book1.showBook();
  16. } catch (CloneNotSupportedException e) {
  17. e.printStackTrace();
  18. }
  19. }

输出结果如下:

  1. =====Start=====
  2. title:书1
  3. image name:图1
  4. ======End======
  5. =====Start=====
  6. title:书1
  7. image name:图1
  8. ======End======
  9. =====Start=====
  10. title:书2
  11. image name:图1
  12. image name:图2
  13. ======End======
  14. =====Start=====
  15. title:书1
  16. image name:图1
  17. image name:图2
  18. ======End======

上述的原型模式的实现实际上只是一个浅拷贝,也称为影子拷贝,并不是将原始对象全都重新构造了一份,而是拷贝对象的字段引用了原始对象的字段。

可以发现,boo2对象在执行book2.addImage("图2")时,book1也会影响到。原因是book2的image只是单纯的指向了this.image引用,并没有重新构造一个image。

而在book2设置title,book1的title并没有发生变化,原因具体见连接:

java克隆中String的特殊性
深入java克隆

深拷贝

修改如下(其他不变):

  1. @Override
  2. protected Object clone() throws CloneNotSupportedException {
  3. Book book = (Book)super.clone();
  4. book.image = (ArrayList<String>) this.image.clone();
  5. return book;
  6. }

4.5 Android源码中的原型模式

5.5.1 原型模式 Intent的实现

示例:

  1. Uri uri = Uri.parse("smsto:110");
  2. Intent intent = new Intent(Intent.ACTION_SEND,uri);
  3. intent.putExtra("sms_body", "The SMS text");
  4. //克隆
  5. Intent intent2 = (Intent)intent.clone();
  6. startActivity(intent2);

看看Intent的clone()方法是如何实现的:

  1. //源码路径:frameworks/base/core/java/android/content/Intent.java
  2. public class Intent implements Parcelable, Cloneable {
  3. @Override
  4. public Object clone() {
  5. return new Intent(this);
  6. }
  7. /**
  8. * Copy constructor.
  9. */
  10. public Intent(Intent o) {
  11. this.mAction = o.mAction;
  12. this.mData = o.mData;
  13. this.mType = o.mType;
  14. this.mPackage = o.mPackage;
  15. this.mComponent = o.mComponent;
  16. this.mFlags = o.mFlags;
  17. this.mContentUserHint = o.mContentUserHint;
  18. if (o.mCategories != null) {
  19. this.mCategories = new ArraySet<String>(o.mCategories);
  20. }
  21. if (o.mExtras != null) {
  22. this.mExtras = new Bundle(o.mExtras);
  23. }
  24. if (o.mSourceBounds != null) {
  25. this.mSourceBounds = new Rect(o.mSourceBounds);
  26. }
  27. if (o.mSelector != null) {
  28. this.mSelector = new Intent(o.mSelector);
  29. }
  30. if (o.mClipData != null) {
  31. this.mClipData = new ClipData(o.mClipData);
  32. }
  33. }
  34. }

clone()方法中并没有调用super.clone()方法来实现对象拷贝,而是调用了new Intent(this)。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注