@Beeder
2017-08-21T08:30:17.000000Z
字数 3269
阅读 1315
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;}@Overrideprotected 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:书1image name:图1======End===========Start=====title:书1image name:图1======End===========Start=====title:书2image name:图1image name:图2======End===========Start=====title:书1image name:图1image name:图2======End======
上述的原型模式的实现实际上只是一个浅拷贝,也称为影子拷贝,并不是将原始对象全都重新构造了一份,而是拷贝对象的字段引用了原始对象的字段。
可以发现,boo2对象在执行book2.addImage("图2")时,book1也会影响到。原因是book2的image只是单纯的指向了this.image引用,并没有重新构造一个image。
而在book2设置title,book1的title并没有发生变化,原因具体见连接:
深拷贝
修改如下(其他不变):
@Overrideprotected 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.javapublic class Intent implements Parcelable, Cloneable {@Overridepublic 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)。