@Beeder
2017-08-21T16:30:17.000000Z
字数 3269
阅读 820
android
用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。被复制的实例就是“原型”,这个原型是可定制的。
注意:clone是Object中的方法
(3)一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用,即保护性拷贝。
应该注意的是:通过clone拷贝对象时并不会执行构造函数,因此,如果在构造函数中需要一些特殊的初始化操作的类型,在实现拷贝时,需要注意构造函数不会执行的问题
角色介绍如下:
* Client:客户端用户。
* Prototype:抽象类或者接口、声明具备clone能力。
* ConcretePrototype:具体的实现类。
浅拷贝
//Book类扮演的是ConcretePrototype角色,Cloneable类扮演的是Prototype角色
public class Book implements Cloneable{
private String title;
private ArrayList<String> image = new ArrayList<String>();
public Book() {
super();
}
public Book(String title) {
super();
this.title = title;
}
public ArrayList<String> getImage(){
return image;
}
public void addImage(String img){
this.image.add(img);
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
@Override
protected Object clone() throws CloneNotSupportedException {
Book book = (Book)super.clone();
book.title = this.title;
book.image = this.image;
return book;
}
public void showBook(){
System.out.println("=====Start=====");
System.out.println("title:"+title);
for(String img : image){
System.out.println("image name:"+img);
}
System.out.println("======End======");
}
}
执行main方法:
public static void main(String[] args) {
try {
Book book1 = new Book("书1");
book1.addImage("图1");
//第1次输出
book1.showBook();
Book book2 = (Book) book1.clone();
//第2次输出
book2.showBook();
book2.setTitle("书2");
book2.addImage("图2");
//第3次输出
book2.showBook();
//第4次输出
book1.showBook();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
输出结果如下:
=====Start=====
title:书1
image name:图1
======End======
=====Start=====
title:书1
image name:图1
======End======
=====Start=====
title:书2
image name:图1
image name:图2
======End======
=====Start=====
title:书1
image name:图1
image name:图2
======End======
上述的原型模式的实现实际上只是一个浅拷贝,也称为影子拷贝,并不是将原始对象全都重新构造了一份,而是拷贝对象的字段引用了原始对象的字段。
可以发现,boo2对象在执行book2.addImage("图2")
时,book1也会影响到。原因是book2的image只是单纯的指向了this.image引用,并没有重新构造一个image。
而在book2设置title,book1的title并没有发生变化,原因具体见连接:
深拷贝
修改如下(其他不变):
@Override
protected Object clone() throws CloneNotSupportedException {
Book book = (Book)super.clone();
book.image = (ArrayList<String>) this.image.clone();
return book;
}
示例:
Uri uri = Uri.parse("smsto:110");
Intent intent = new Intent(Intent.ACTION_SEND,uri);
intent.putExtra("sms_body", "The SMS text");
//克隆
Intent intent2 = (Intent)intent.clone();
startActivity(intent2);
看看Intent的clone()方法是如何实现的:
//源码路径:frameworks/base/core/java/android/content/Intent.java
public class Intent implements Parcelable, Cloneable {
@Override
public Object clone() {
return new Intent(this);
}
/**
* Copy constructor.
*/
public Intent(Intent o) {
this.mAction = o.mAction;
this.mData = o.mData;
this.mType = o.mType;
this.mPackage = o.mPackage;
this.mComponent = o.mComponent;
this.mFlags = o.mFlags;
this.mContentUserHint = o.mContentUserHint;
if (o.mCategories != null) {
this.mCategories = new ArraySet<String>(o.mCategories);
}
if (o.mExtras != null) {
this.mExtras = new Bundle(o.mExtras);
}
if (o.mSourceBounds != null) {
this.mSourceBounds = new Rect(o.mSourceBounds);
}
if (o.mSelector != null) {
this.mSelector = new Intent(o.mSelector);
}
if (o.mClipData != null) {
this.mClipData = new ClipData(o.mClipData);
}
}
}
clone()方法中并没有调用super.clone()方法来实现对象拷贝,而是调用了new Intent(this)。